/*
 * Copyright (c) 2009, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */
package com.sun.classanalyzer;

import com.sun.tools.classfile.*;
import com.sun.tools.classfile.Type.*;
import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
import static com.sun.tools.classfile.AccessFlags.*;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

/**
 *
 * @author Mandy Chung
 */
public class ClassFileParser {

    final Klass this_klass;
    final ClassFile classfile;
    final ConstantPoolParser constantPoolParser;
    final AnnotationParser annotationParser;
    final CodeAttributeParser codeAttributeParser;
    private final boolean buildDeps;

    protected ClassFileParser(InputStream in, long size, boolean buildDeps) throws IOException {
        try {
            this.classfile = ClassFile.read(in);
            this.this_klass = getKlass(this.classfile);
            this.buildDeps = buildDeps;
            this.constantPoolParser = new ConstantPoolParser(this);
            this.annotationParser = new AnnotationParser(this);
            this.codeAttributeParser = new CodeAttributeParser(this);
        } catch (ConstantPoolException ex) {
            throw new RuntimeException(ex);
        }
    }

    private Klass getKlass(ClassFile cf) throws ConstantPoolException {
        Klass k = Klass.getKlass(cf.getName());
        k.setAccessFlags(cf.access_flags.flags);
        k.setFileSize(cf.byteLength());
        return k;
    }

    public static ClassFileParser newParser(InputStream in, long size, boolean buildDeps) throws IOException {
        return new ClassFileParser(in, size, buildDeps);
    }

    public static ClassFileParser newParser(String classPathname, boolean buildDeps) throws IOException {
        return newParser(new File(classPathname), buildDeps);
    }

    public static ClassFileParser newParser(File f, boolean buildDeps) throws IOException {
        BufferedInputStream in = new BufferedInputStream(new FileInputStream(f));
        try {
            return newParser(in, f.length(), buildDeps);
        } finally {
            in.close();
        }
    }

    public void parseDependency(boolean publicAPIs) throws IOException {
        if (publicAPIs && !classfile.access_flags.is(ACC_PUBLIC)) {
            // process public APIs only
            return;
        }

        parseClassInfo();
        if (!publicAPIs) {
            // parse all references in the classfile
            constantPoolParser.parseDependency();
        }
        parseMethods(publicAPIs);
        parseFields(publicAPIs);
    }

    void parseClassInfo() throws IOException {
        ConstantPool cpool = classfile.constant_pool;
        try {
            Signature_attribute sigAttr = (Signature_attribute) classfile.attributes.get(Attribute.Signature);
            if (sigAttr == null) {
                // use info from class file header
                if (classfile.isClass() && classfile.super_class != 0) {
                    String sn = classfile.getSuperclassName();
                    addExtends(sn);
                }
                for (int i = 0; i < classfile.interfaces.length; i++) {
                    String interf = classfile.getInterfaceName(i);
                    if (classfile.isClass()) {
                        addImplements(interf);
                    } else {
                        addExtends(interf);
                    }
                }
            } else {
                Type t = sigAttr.getParsedSignature().getType(cpool);
                // The signature parser cannot disambiguate between a
                // FieldType and a ClassSignatureType that only contains a superclass type.
                if (t instanceof Type.ClassSigType) {
                    Type.ClassSigType cst = Type.ClassSigType.class.cast(t);
                    if (cst.superclassType != null) {
                        for (Klass k : getKlass(cst.superclassType)) {
                            addExtends(k);
                        }
                    }
                    if (cst.superinterfaceTypes != null) {
                        for (Type t1 : cst.superinterfaceTypes) {
                            for (Klass k : getKlass(t1)) {
                                addImplements(k);
                            }
                        }
                    }
                } else {
                    for (Klass k : getKlass(t)) {
                        addExtends(k);
                    }
                }
            }
            // parse attributes
            annotationParser.parseAttributes(classfile.attributes);
        } catch (ConstantPoolException ex) {
            throw new RuntimeException(ex);
        }
    }

    private void parseFields(boolean publicAPIs) throws IOException {
        ConstantPool cpool = classfile.constant_pool;
        for (Field f : classfile.fields) {
            try {
                AccessFlags flags = f.access_flags;
                if (publicAPIs && !flags.is(ACC_PUBLIC) && !flags.is(ACC_PROTECTED)) {
                    continue;
                }
                String fieldname = f.getName(cpool);
                Signature_attribute sigAttr = (Signature_attribute) f.attributes.get(Attribute.Signature);

                if (sigAttr == null) {
                    Set<Klass> types = parseDescriptor(f.descriptor);
                    String info = getFlag(flags) + " " + f.descriptor.getFieldType(cpool) + " " + fieldname;
                    addFieldTypes(types, info, flags);
                } else {
                    Type t = sigAttr.getParsedSignature().getType(cpool);
                    String info = getFlag(flags) + " " + t + " " + fieldname;
                    addFieldTypes(getKlass(t), info, flags);
                }
                // parse attributes
                annotationParser.parseAttributes(f.attributes);
            } catch (ConstantPoolException ex) {
                throw new RuntimeException(ex);
            } catch (InvalidDescriptor ex) {
                throw new RuntimeException(ex);
            }
        }
    }

    private void parseMethods(boolean publicAPIs) {
        for (Method m : classfile.methods) {
            if (publicAPIs && !m.access_flags.is(ACC_PUBLIC) && !m.access_flags.is(ACC_PROTECTED)) {
                // only interest in the API level
                return;
            }

            parseMethod(m);
        }
    }

    String checkClassName(String classname) {
        int i = 0;
        while (i < classname.length()) {
            switch (classname.charAt(i)) {
                case 'Z':
                case 'B':
                case 'C':
                case 'S':
                case 'I':
                case 'J':
                case 'F':
                case 'D':
                    return "";
                case 'L':
                    if (!classname.endsWith(";")) {
                        throw new RuntimeException("Invalid classname " + classname);
                    }
                    return classname.substring(i + 1, classname.length() - 1);
                case '[':
                    i++;
                    break;
                default:
                    if (classname.endsWith(";")) {
                        throw new RuntimeException("Invalid classname " + classname);
                    }
                    return classname;

            }
        }
        throw new RuntimeException("Invalid classname " + classname);
    }

    private void addExtends(String classname) throws IOException {
        if (!buildDeps) {
            return;
        }

        addExtends(Klass.getKlass(classname));
    }

    private void addExtends(Klass k) {
        if (!buildDeps) {
            return;
        }

        ResolutionInfo resInfo = ResolutionInfo.resolvedExtends(this_klass, k);
        resInfo.setPublicAccess(classfile.access_flags.is(ACC_PUBLIC));
        this_klass.addDep(k, resInfo);
        k.addReferrer(this_klass, resInfo);
    }

    private void addImplements(String classname) throws IOException {
        if (!buildDeps) {
            return;
        }

        addImplements(Klass.getKlass(classname));
    }

    private void addImplements(Klass k) {
        if (!buildDeps) {
            return;
        }

        ResolutionInfo resInfo = ResolutionInfo.resolvedImplements(this_klass, k);
        resInfo.setPublicAccess(classfile.access_flags.is(ACC_PUBLIC));

        this_klass.addDep(k, resInfo);

        k.addReferrer(this_klass, resInfo);
    }

    private Set<Klass> getKlass(Type type) throws IOException {
        Set<Klass> refTypes = new TreeSet<Klass>();
        if (!buildDeps) {
            return refTypes;
        }

        type.accept(typevisitor, refTypes);
        return refTypes;
    }
    private Type.Visitor<Void, Set<Klass>> typevisitor = new Type.Visitor<Void, Set<Klass>>() {

        public Void visitSimpleType(SimpleType type, Set<Klass> klasses) {
            // nop
            return null;
        }

        public Void visitArrayType(ArrayType type, Set<Klass> klasses) {
            try {
                klasses.addAll(getKlass(type.elemType));
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
            return null;

        }

        public Void visitMethodType(MethodType type, Set<Klass> klasses) {
            throw new InternalError("Unexpected type " + type);
        }

        public Void visitClassSigType(ClassSigType type, Set<Klass> klasses) {
            try {
                if (type.superclassType != null) {
                    klasses.addAll(getKlass(type.superclassType));
                }
                if (type.superinterfaceTypes != null) {
                    for (Type t : type.superinterfaceTypes) {
                        klasses.addAll(getKlass(t));
                    }
                }
                if (type.typeParamTypes != null) {
                    for (Type t : type.typeParamTypes) {
                        klasses.addAll(getKlass(t));
                    }
                }
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
            return null;
        }

        public Void visitClassType(ClassType type, Set<Klass> klasses) {
            klasses.add(Klass.getKlass(type.getBinaryName()));
            if (type.typeArgs != null) {
                for (Type t : type.typeArgs) {
                    try {
                        klasses.addAll(getKlass(t));
                    } catch (IOException ex) {
                        throw new RuntimeException(ex);
                    }
                }
            }
            return null;

        }

        public Void visitTypeParamType(TypeParamType type, Set<Klass> klasses) {
            try {
                if (type.classBound != null) {
                    klasses.addAll(getKlass(type.classBound));
                }
                if (type.interfaceBounds != null) {
                    for (Type t : type.interfaceBounds) {
                        klasses.addAll(getKlass(t));
                    }
                }

            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }

            return null;

        }

        public Void visitWildcardType(WildcardType type, Set<Klass> klasses) {
            if (type.boundType != null) {
                try {
                    klasses.addAll(getKlass(type.boundType));
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
            }
            return null;

        }
    };

    private void printMethod(Method m) {
        try {
            System.out.println("parsing " + m.getName(classfile.constant_pool) + "(" +
                    m.descriptor.getParameterTypes(classfile.constant_pool) + ") return type " +
                    m.descriptor.getReturnType(classfile.constant_pool));

        } catch (ConstantPoolException ex) {
        } catch (InvalidDescriptor ex) {
        }
    }

    private static StringBuilder appendWord(StringBuilder sb, String word) {
        if (sb.length() > 0) {
            sb.append(" ");
        }
        sb.append(word);
        return sb;
    }

    private static String getFlag(AccessFlags flags) {
        StringBuilder modifier = new StringBuilder();
        if (flags.is(ACC_PUBLIC)) {
            modifier.append("public");
        }
        if (flags.is(ACC_PRIVATE)) {
            modifier.append("private");
        }
        if (flags.is(ACC_PROTECTED)) {
            modifier.append("protected");
        }
        if (flags.is(ACC_STATIC)) {
            appendWord(modifier, "static");
        }
        if (flags.is(ACC_FINAL)) {
            appendWord(modifier, "final");
        }
        if (flags.is(ACC_SYNCHRONIZED)) {
            // return "synchronized";
        }
        if (flags.is(0x80)) {
            // return (t == Type.Field ? "transient" : null);
            // return "transient";
        }
        if (flags.is(ACC_VOLATILE)) {
            // return "volatile";
        }
        if (flags.is(ACC_NATIVE)) {
            // return "native";
        }
        if (flags.is(ACC_ABSTRACT)) {
            appendWord(modifier, "abstract");
        }
        if (flags.is(ACC_STRICT)) {
            // return "strictfp";
        }
        if (flags.is(ACC_MODULE)) {
            appendWord(modifier, "module");
        }
        return modifier.toString();
    }

    private Klass.Method toKlassMethod(Method m, Descriptor d) {
        try {
            ConstantPool cpool = classfile.constant_pool;
            String methodname = m.getName(cpool);
            StringBuilder sb = new StringBuilder();
            sb.append(getFlag(m.access_flags));
            if (methodname.equals("<init>")) {
                String s = this_klass.getBasename() + d.getParameterTypes(cpool);
                appendWord(sb, s);
            } else if (methodname.equals("<clinit>")) {
                // <clinit>
                appendWord(sb, methodname);
            } else {
                String s = d.getReturnType(cpool) + " " + methodname + d.getParameterTypes(cpool);
                appendWord(sb, s);
            }
            String signature = sb.toString().replace('/', '.');
            return this_klass.getMethod(methodname, signature);
        } catch (ConstantPoolException ex) {
            throw new RuntimeException(ex);
        } catch (InvalidDescriptor ex) {
            throw new RuntimeException(ex);
        }
    }

    Klass.Method parseMethod(Method m) {
        AccessFlags flags = m.access_flags;
        Descriptor d;
        List<? extends Type> methodExceptions = null;
        try {
            ConstantPool cpool = classfile.constant_pool;
            Klass.Method kmethod;
            Signature_attribute sigAttr = (Signature_attribute) m.attributes.get(Attribute.Signature);
            if (sigAttr == null) {
                d = m.descriptor;
                Set<Klass> types = parseDescriptor(d);

                kmethod = toKlassMethod(m, d);
                addMethodTypes(types, kmethod, flags);
            } else {
                Type.MethodType methodType;
                Signature methodSig = sigAttr.getParsedSignature();
                d = methodSig;
                try {
                    kmethod = toKlassMethod(m, d);
                    methodType = (Type.MethodType) methodSig.getType(cpool);
                    addMethodTypes(getKlass(methodType.returnType), kmethod, flags);
                    if (methodType.paramTypes != null) {
                        for (Type t : methodType.paramTypes) {
                            addMethodTypes(getKlass(t), kmethod, flags);
                        }
                    }
                    if (methodType.typeParamTypes != null) {
                        for (Type t : methodType.typeParamTypes) {
                            addMethodTypes(getKlass(t), kmethod, flags);
                        }
                    }

                    methodExceptions = methodType.throwsTypes;
                    if (methodExceptions != null) {
                        if (methodExceptions.size() == 0) {
                            methodExceptions = null;
                        } else {
                            for (Type t : methodExceptions) {
                                addCheckedExceptionTypes(getKlass(t), kmethod, flags);
                            }
                        }
                    }
                } catch (ConstantPoolException e) {
                    throw new RuntimeException(e);
                }
            }

            Attribute e_attr = m.attributes.get(Attribute.Exceptions);
            if (e_attr != null && methodExceptions == null) {
                // if there are generic exceptions, there must be erased exceptions
                if (e_attr instanceof Exceptions_attribute) {
                    Exceptions_attribute exceptions = (Exceptions_attribute) e_attr;
                    for (int i = 0; i < exceptions.number_of_exceptions; i++) {
                        String classname = checkClassName(exceptions.getException(i, classfile.constant_pool));
                        if (classname.length() > 0 && buildDeps) {
                            Klass to = Klass.getKlass(classname);
                            ResolutionInfo resInfo = ResolutionInfo.resolvedCheckedException(this_klass, to, kmethod);
                            resInfo.setPublicAccess(flags.is(ACC_PUBLIC));

                            this_klass.addDep(to, resInfo);
                            to.addReferrer(this_klass, resInfo);
                        }
                    }
                } else {
                    throw new RuntimeException("Invalid attribute: " + e_attr);
                }
            }

            Code_attribute c_attr = (Code_attribute) m.attributes.get(Attribute.Code);
            if (c_attr != null) {
                codeAttributeParser.parse(c_attr, kmethod);
            }
            kmethod.isAbstract = classfile.access_flags.is(ACC_ABSTRACT);
            kmethod.setCodeLength(m.byteLength());

            // parse annotation attributes
            annotationParser.parseAttributes(m.attributes, kmethod);
            return kmethod;
        } catch (ConstantPoolException ex) {
            throw new RuntimeException(ex);
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    private void addFieldTypes(Set<Klass> types, String info, AccessFlags flags) {
        if (types.isEmpty() || !buildDeps) {
            return;
        }

        for (Klass to : types) {
            ResolutionInfo resInfo = ResolutionInfo.resolvedField(this_klass, to, info);
            resInfo.setPublicAccess(flags.is(ACC_PUBLIC));

            this_klass.addDep(to, resInfo);
            to.addReferrer(this_klass, resInfo);
        }
    }

    private void addReferencedTypes(Method m, Descriptor d, AccessFlags flags) {
        Set<Klass> types = parseDescriptor(d);

        Klass.Method method = toKlassMethod(m, d);
        addMethodTypes(types, method, flags);
    }

    private void addMethodTypes(Set<Klass> types, Klass.Method method, AccessFlags flags) {
        if (types.isEmpty() || !buildDeps) {
            return;
        }
        for (Klass to : types) {
            ResolutionInfo resInfo = ResolutionInfo.resolvedMethodSignature(this_klass, to, method);
            resInfo.setPublicAccess(flags.is(ACC_PUBLIC));

            this_klass.addDep(to, resInfo);
            to.addReferrer(this_klass, resInfo);
        }
    }

    private void addCheckedExceptionTypes(Set<Klass> types, Klass.Method method, AccessFlags flags) {
        if (types.isEmpty() || !buildDeps) {
            return;
        }
        for (Klass to : types) {
            ResolutionInfo resInfo = ResolutionInfo.resolvedCheckedException(this_klass, to, method);
            resInfo.setPublicAccess(flags.is(ACC_PUBLIC));

            this_klass.addDep(to, resInfo);
            to.addReferrer(this_klass, resInfo);
        }
    }

    private Set<Klass> parseDescriptor(Descriptor d) {
        Set<Klass> types = new TreeSet<Klass>();
        try {
            String desc = d.getValue(classfile.constant_pool);
            int p = 0;
            while (p < desc.length()) {
                String type;
                char ch;
                switch (ch = desc.charAt(p++)) {
                    case '(':
                    case ')':
                    case '[':
                    case 'B':
                    case 'C':
                    case 'D':
                    case 'F':
                    case 'I':
                    case 'J':
                    case 'S':
                    case 'Z':
                    case 'V':
                        continue;
                    case 'L':
                        int sep = desc.indexOf(';', p);
                        if (sep == -1) {
                            throw new RuntimeException("Invalid descriptor: " + (p - 1) + " " + desc);
                        }
                        type = checkClassName(desc.substring(p, sep));
                        p = sep + 1;
                        break;
                    default:
                        throw new RuntimeException("Invalid descriptor: " + (p - 1) + " " + desc);
                }

                if (!type.isEmpty() && buildDeps) {
                    Klass to = Klass.getKlass(type);
                    types.add(to);

                }
            }
        } catch (ConstantPoolException ex) {
            throw new RuntimeException(ex);
        }
        return types;
    }
}
