/*
 * ProGuard -- shrinking, optimization, obfuscation, and preverification
 *             of Java bytecode.
 *
 * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu)
 *
 * This program 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.
 *
 * This program 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 this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
package proguard.classfile.io;

import proguard.classfile.*;
import proguard.classfile.constant.*;
import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.util.*;
import proguard.classfile.visitor.*;

import java.io.DataInput;

/**
 * This ClassVisitor fills out the LibraryClass objects that it visits with data
 * from the given DataInput object.
 *
 * @author Eric Lafortune
 */
public class LibraryClassReader
extends      SimplifiedVisitor
implements   ClassVisitor,
             MemberVisitor,
             ConstantVisitor
{
    private static final LibraryField[]  EMPTY_LIBRARY_FIELDS  = new LibraryField[0];
    private static final LibraryMethod[] EMPTY_LIBRARY_METHODS = new LibraryMethod[0];


    private final RuntimeDataInput dataInput;
    private final boolean          skipNonPublicClasses;
    private final boolean          skipNonPublicClassMembers;

    // A global array that acts as a parameter for the visitor methods.
    private Constant[]      constantPool;


    /**
     * Creates a new ProgramClassReader for reading from the given DataInput.
     */
    public LibraryClassReader(DataInput dataInput,
                              boolean   skipNonPublicClasses,
                              boolean   skipNonPublicClassMembers)
    {
        this.dataInput                 = new RuntimeDataInput(dataInput);
        this.skipNonPublicClasses      = skipNonPublicClasses;
        this.skipNonPublicClassMembers = skipNonPublicClassMembers;
    }


    // Implementations for ClassVisitor.

    public void visitProgramClass(ProgramClass libraryClass)
    {
    }


    public void visitLibraryClass(LibraryClass libraryClass)
    {
        // Read and check the magic number.
        int u4magic = dataInput.readInt();

        ClassUtil.checkMagicNumber(u4magic);

        // Read and check the version numbers.
        int u2minorVersion = dataInput.readUnsignedShort();
        int u2majorVersion = dataInput.readUnsignedShort();

        int u4version = ClassUtil.internalClassVersion(u2majorVersion,
                                                       u2minorVersion);

        ClassUtil.checkVersionNumbers(u4version);

        // Read the constant pool. Note that the first entry is not used.
        int u2constantPoolCount = dataInput.readUnsignedShort();

        // Create the constant pool array.
        constantPool = new Constant[u2constantPoolCount];

        for (int index = 1; index < u2constantPoolCount; index++)
        {
            Constant constant = createConstant();
            constant.accept(libraryClass, this);

            int tag = constant.getTag();
            if (tag == ClassConstants.CONSTANT_Class ||
                tag == ClassConstants.CONSTANT_Utf8)
            {
                constantPool[index] = constant;
            }

            // Long constants and double constants take up two entries in the
            // constant pool.
            if (tag == ClassConstants.CONSTANT_Long ||
                tag == ClassConstants.CONSTANT_Double)
            {
                index++;
            }
        }

        // Read the general class information.
        libraryClass.u2accessFlags = dataInput.readUnsignedShort();

        // We may stop parsing this library class if it's not public anyway.
        // E.g. only about 60% of all rt.jar classes need to be parsed.
        if (skipNonPublicClasses &&
            AccessUtil.accessLevel(libraryClass.getAccessFlags()) < AccessUtil.PUBLIC)
        {
            return;
        }

        // Read the class and super class indices.
        int u2thisClass  = dataInput.readUnsignedShort();
        int u2superClass = dataInput.readUnsignedShort();

        // Store their actual names.
        libraryClass.thisClassName  = getClassName(u2thisClass);
        libraryClass.superClassName = (u2superClass == 0) ? null :
                                      getClassName(u2superClass);

        // Read the interfaces
        int u2interfacesCount = dataInput.readUnsignedShort();

        libraryClass.interfaceNames = new String[u2interfacesCount];
        for (int index = 0; index < u2interfacesCount; index++)
        {
            // Store the actual interface name.
            int u2interface = dataInput.readUnsignedShort();
            libraryClass.interfaceNames[index] = getClassName(u2interface);
        }

        // Read the fields.
        int u2fieldsCount = dataInput.readUnsignedShort();

        // Create the fields array.
        LibraryField[] reusableFields = new LibraryField[u2fieldsCount];

        int visibleFieldsCount = 0;
        for (int index = 0; index < u2fieldsCount; index++)
        {
            LibraryField field = new LibraryField();
            this.visitLibraryMember(libraryClass, field);

            // Only store fields that are visible.
            if (AccessUtil.accessLevel(field.getAccessFlags()) >=
                (skipNonPublicClassMembers ? AccessUtil.PROTECTED :
                                             AccessUtil.PACKAGE_VISIBLE))
            {
                reusableFields[visibleFieldsCount++] = field;
            }
        }

        // Copy the visible fields (if any) into a fields array of the right size.
        if (visibleFieldsCount == 0)
        {
            libraryClass.fields = EMPTY_LIBRARY_FIELDS;
        }
        else
        {
            libraryClass.fields = new LibraryField[visibleFieldsCount];
            System.arraycopy(reusableFields, 0, libraryClass.fields, 0, visibleFieldsCount);
        }

        // Read the methods.
        int u2methodsCount = dataInput.readUnsignedShort();

        // Create the methods array.
        LibraryMethod[] reusableMethods = new LibraryMethod[u2methodsCount];

        int visibleMethodsCount = 0;
        for (int index = 0; index < u2methodsCount; index++)
        {
            LibraryMethod method = new LibraryMethod();
            this.visitLibraryMember(libraryClass, method);

            // Only store methods that are visible.
            if (AccessUtil.accessLevel(method.getAccessFlags()) >=
                (skipNonPublicClassMembers ? AccessUtil.PROTECTED :
                                             AccessUtil.PACKAGE_VISIBLE))
            {
                reusableMethods[visibleMethodsCount++] = method;
            }
        }

        // Copy the visible methods (if any) into a methods array of the right size.
        if (visibleMethodsCount == 0)
        {
            libraryClass.methods = EMPTY_LIBRARY_METHODS;
        }
        else
        {
            libraryClass.methods = new LibraryMethod[visibleMethodsCount];
            System.arraycopy(reusableMethods, 0, libraryClass.methods, 0, visibleMethodsCount);
        }

        // Skip the class attributes.
        skipAttributes();
    }


    // Implementations for MemberVisitor.

    public void visitProgramMember(ProgramClass libraryClass, ProgramMember libraryMember)
    {
    }


    public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember)
    {
        // Read the general field information.
        libraryMember.u2accessFlags = dataInput.readUnsignedShort();
        libraryMember.name          = getString(dataInput.readUnsignedShort());
        libraryMember.descriptor    = getString(dataInput.readUnsignedShort());

        // Skip the field attributes.
        skipAttributes();
    }


    // Implementations for ConstantVisitor.

    public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
    {
        dataInput.skipBytes(4);
    }


    public void visitLongConstant(Clazz clazz, LongConstant longConstant)
    {
        dataInput.skipBytes(8);
    }


    public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
    {
        dataInput.skipBytes(4);
    }


    public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
    {
        dataInput.skipBytes(8);
    }


    public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
    {
        dataInput.skipBytes(2);
    }


    public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
    {
        int u2length = dataInput.readUnsignedShort();

        // Read the UTF-8 bytes.
        byte[] bytes = new byte[u2length];
        dataInput.readFully(bytes);
        utf8Constant.setBytes(bytes);
    }


    public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
    {
        dataInput.skipBytes(4);
    }


    public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
    {
        dataInput.skipBytes(3);
    }


    public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
    {
        dataInput.skipBytes(4);
    }


    public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
    {
        classConstant.u2nameIndex = dataInput.readUnsignedShort();
    }


    public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
    {
        dataInput.skipBytes(2);
    }


    public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
    {
        dataInput.skipBytes(4);
    }


    // Small utility methods.

    /**
     * Returns the class name of the ClassConstant at the specified index in the
     * reusable constant pool.
     */
    private String getClassName(int constantIndex)
    {
        ClassConstant classEntry = (ClassConstant)constantPool[constantIndex];

        return getString(classEntry.u2nameIndex);
    }


    /**
     * Returns the string of the Utf8Constant at the specified index in the
     * reusable constant pool.
     */
    private String getString(int constantIndex)
    {
        return ((Utf8Constant)constantPool[constantIndex]).getString();
    }


    private Constant createConstant()
    {
        int u1tag = dataInput.readUnsignedByte();

        switch (u1tag)
        {
            case ClassConstants.CONSTANT_Integer:            return new IntegerConstant();
            case ClassConstants.CONSTANT_Float:              return new FloatConstant();
            case ClassConstants.CONSTANT_Long:               return new LongConstant();
            case ClassConstants.CONSTANT_Double:             return new DoubleConstant();
            case ClassConstants.CONSTANT_String:             return new StringConstant();
            case ClassConstants.CONSTANT_Utf8:               return new Utf8Constant();
            case ClassConstants.CONSTANT_InvokeDynamic:      return new InvokeDynamicConstant();
            case ClassConstants.CONSTANT_MethodHandle:       return new MethodHandleConstant();
            case ClassConstants.CONSTANT_Fieldref:           return new FieldrefConstant();
            case ClassConstants.CONSTANT_Methodref:          return new MethodrefConstant();
            case ClassConstants.CONSTANT_InterfaceMethodref: return new InterfaceMethodrefConstant();
            case ClassConstants.CONSTANT_Class:              return new ClassConstant();
            case ClassConstants.CONSTANT_MethodType:         return new MethodTypeConstant();
            case ClassConstants.CONSTANT_NameAndType:        return new NameAndTypeConstant();

            default: throw new RuntimeException("Unknown constant type ["+u1tag+"] in constant pool");
        }
    }


    private void skipAttributes()
    {
        int u2attributesCount = dataInput.readUnsignedShort();

        for (int index = 0; index < u2attributesCount; index++)
        {
            skipAttribute();
        }
    }


    private void skipAttribute()
    {
        dataInput.skipBytes(2);
        int u4attributeLength = dataInput.readInt();
        dataInput.skipBytes(u4attributeLength);
    }
}
