/*
 * Copyright (c) 1994, 2006, 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * 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 sun.tools.java;

import java.io.IOException;
import java.io.DataInputStream;
import java.io.OutputStream;
import java.io.DataOutputStream;
import java.io.ByteArrayInputStream;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Enumeration;

/**
 * WARNING: The contents of this source file are not part of any
 * supported API.  Code that depends on them does so at its own risk:
 * they are subject to change or removal without notice.
 */
public final
class BinaryClass extends ClassDefinition implements Constants {
    BinaryConstantPool cpool;
    BinaryAttribute atts;
    Vector dependencies;
    private boolean haveLoadedNested = false;

    /**
     * Constructor
     */
    public BinaryClass(Object source, ClassDeclaration declaration, int modifiers,
                           ClassDeclaration superClass, ClassDeclaration interfaces[],
                           Vector dependencies) {
        super(source, 0, declaration, modifiers, null, null);
        this.dependencies = dependencies;
        this.superClass = superClass;
        this.interfaces = interfaces;
    }

    /**
     * Flags used by basicCheck() to avoid duplicate calls.
     * (Part of fix for 4105911)
     */
    private boolean basicCheckDone = false;
    private boolean basicChecking = false;

    /**
     * Ready a BinaryClass for further checking.  Note that, until recently,
     * BinaryClass relied on the default basicCheck() provided by
     * ClassDefinition.  The definition here has been added to ensure that
     * the information generated by collectInheritedMethods is available
     * for BinaryClasses.
     */
    protected void basicCheck(Environment env) throws ClassNotFound {
        if (tracing) env.dtEnter("BinaryClass.basicCheck: " + getName());

        // We need to guard against duplicate calls to basicCheck().  They
        // can lead to calling collectInheritedMethods() for this class
        // from within a previous call to collectInheritedMethods() for
        // this class.  That is not allowed.
        // (Part of fix for 4105911)
        if (basicChecking || basicCheckDone) {
            if (tracing) env.dtExit("BinaryClass.basicCheck: OK " + getName());
            return;
        }

        if (tracing) env.dtEvent("BinaryClass.basicCheck: CHECKING " + getName());
        basicChecking = true;

        super.basicCheck(env);

        // Collect inheritance information.
        if (doInheritanceChecks) {
            collectInheritedMethods(env);
        }

        basicCheckDone = true;
        basicChecking = false;
        if (tracing) env.dtExit("BinaryClass.basicCheck: " + getName());
    }

    /**
     * Load a binary class
     */
    public static BinaryClass load(Environment env, DataInputStream in) throws IOException {
        return load(env, in, ~(ATT_CODE|ATT_ALLCLASSES));
    }

    public static BinaryClass load(Environment env,
                                   DataInputStream in, int mask) throws IOException {
        // Read the header
        int magic = in.readInt();                    // JVM 4.1 ClassFile.magic
        if (magic != JAVA_MAGIC) {
            throw new ClassFormatError("wrong magic: " + magic + ", expected " + JAVA_MAGIC);
        }
        int minor_version = in.readUnsignedShort();  // JVM 4.1 ClassFile.minor_version
        int version = in.readUnsignedShort();        // JVM 4.1 ClassFile.major_version
        if (version < JAVA_MIN_SUPPORTED_VERSION) {
            throw new ClassFormatError(
                           sun.tools.javac.Main.getText(
                               "javac.err.version.too.old",
                               String.valueOf(version)));
        } else if ((version > JAVA_MAX_SUPPORTED_VERSION)
                     || (version == JAVA_MAX_SUPPORTED_VERSION
                  && minor_version > JAVA_MAX_SUPPORTED_MINOR_VERSION)) {
            throw new ClassFormatError(
                           sun.tools.javac.Main.getText(
                               "javac.err.version.too.recent",
                               version+"."+minor_version));
        }

        // Read the constant pool
        BinaryConstantPool cpool = new BinaryConstantPool(in);

        // The dependencies of this class
        Vector dependencies = cpool.getDependencies(env);

        // Read modifiers
        int classMod = in.readUnsignedShort() & ACCM_CLASS;  // JVM 4.1 ClassFile.access_flags

        // Read the class name - from JVM 4.1 ClassFile.this_class
        ClassDeclaration classDecl = cpool.getDeclaration(env, in.readUnsignedShort());

        // Read the super class name (may be null) - from JVM 4.1 ClassFile.super_class
        ClassDeclaration superClassDecl = cpool.getDeclaration(env, in.readUnsignedShort());

        // Read the interface names - from JVM 4.1 ClassFile.interfaces_count
        ClassDeclaration interfaces[] = new ClassDeclaration[in.readUnsignedShort()];
        for (int i = 0 ; i < interfaces.length ; i++) {
            // JVM 4.1 ClassFile.interfaces[]
            interfaces[i] = cpool.getDeclaration(env, in.readUnsignedShort());
        }

        // Allocate the class
        BinaryClass c = new BinaryClass(null, classDecl, classMod, superClassDecl,
                                        interfaces, dependencies);
        c.cpool = cpool;

        // Add any additional dependencies
        c.addDependency(superClassDecl);

        // Read the fields
        int nfields = in.readUnsignedShort();  // JVM 4.1 ClassFile.fields_count
        for (int i = 0 ; i < nfields ; i++) {
            // JVM 4.5 field_info.access_flags
            int fieldMod = in.readUnsignedShort() & ACCM_FIELD;
            // JVM 4.5 field_info.name_index
            Identifier fieldName = cpool.getIdentifier(in.readUnsignedShort());
            // JVM 4.5 field_info.descriptor_index
            Type fieldType = cpool.getType(in.readUnsignedShort());
            BinaryAttribute atts = BinaryAttribute.load(in, cpool, mask);
            c.addMember(new BinaryMember(c, fieldMod, fieldType, fieldName, atts));
        }

        // Read the methods
        int nmethods = in.readUnsignedShort();  // JVM 4.1 ClassFile.methods_count
        for (int i = 0 ; i < nmethods ; i++) {
            // JVM 4.6 method_info.access_flags
            int methMod = in.readUnsignedShort() & ACCM_METHOD;
            // JVM 4.6 method_info.name_index
            Identifier methName = cpool.getIdentifier(in.readUnsignedShort());
            // JVM 4.6 method_info.descriptor_index
            Type methType = cpool.getType(in.readUnsignedShort());
            BinaryAttribute atts = BinaryAttribute.load(in, cpool, mask);
            c.addMember(new BinaryMember(c, methMod, methType, methName, atts));
        }

        // Read the class attributes
        c.atts = BinaryAttribute.load(in, cpool, mask);

        // See if the SourceFile is known
        byte data[] = c.getAttribute(idSourceFile);
        if (data != null) {
            DataInputStream dataStream = new DataInputStream(new ByteArrayInputStream(data));
            // JVM 4.7.2 SourceFile_attribute.sourcefile_index
            c.source = cpool.getString(dataStream.readUnsignedShort());
        }

        // See if the Documentation is know
        data = c.getAttribute(idDocumentation);
        if (data != null) {
            c.documentation = new DataInputStream(new ByteArrayInputStream(data)).readUTF();
        }

        // Was it compiled as deprecated?
        if (c.getAttribute(idDeprecated) != null) {
            c.modifiers |= M_DEPRECATED;
        }

        // Was it synthesized by the compiler?
        if (c.getAttribute(idSynthetic) != null) {
            c.modifiers |= M_SYNTHETIC;
        }

        return c;
    }

    /**
     * Called when an environment ties a binary definition to a declaration.
     * At this point, auxiliary definitions may be loaded.
     */

    public void loadNested(Environment env) {
        loadNested(env, 0);
    }

    public void loadNested(Environment env, int flags) {
        // Sanity check.
        if (haveLoadedNested) {
            // Duplicate calls most likely should not occur, but they do
            // in javap.  Be tolerant of them for the time being.
            // throw new CompilerError("multiple loadNested");
            if (tracing) env.dtEvent("loadNested: DUPLICATE CALL SKIPPED");
            return;
        }
        haveLoadedNested = true;
        // Read class-nesting information.
        try {
            byte data[];
            data = getAttribute(idInnerClasses);
            if (data != null) {
                initInnerClasses(env, data, flags);
            }
        } catch (IOException ee) {
            // The inner classes attribute is not well-formed.
            // It may, for example, contain no data.  Report this.
            // We used to throw a CompilerError here (bug 4095108).
            env.error(0, "malformed.attribute", getClassDeclaration(),
                      idInnerClasses);
            if (tracing)
                env.dtEvent("loadNested: MALFORMED ATTRIBUTE (InnerClasses)");
        }
    }

    private void initInnerClasses(Environment env,
                                  byte data[],
                                  int flags) throws IOException {
        DataInputStream ds = new DataInputStream(new ByteArrayInputStream(data));
        int nrec = ds.readUnsignedShort();  // InnerClasses_attribute.number_of_classes
        for (int i = 0; i < nrec; i++) {
            // For each inner class name transformation, we have a record
            // with the following fields:
            //
            //    u2 inner_class_info_index;   // CONSTANT_Class_info index
            //    u2 outer_class_info_index;   // CONSTANT_Class_info index
            //    u2 inner_name_index;         // CONSTANT_Utf8_info index
            //    u2 inner_class_access_flags; // access_flags bitmask
            //
            // The spec states that outer_class_info_index is 0 iff
            // the inner class is not a member of its enclosing class (i.e.
            // it is a local or anonymous class).  The spec also states
            // that if a class is anonymous then inner_name_index should
            // be 0.
            //
            // Prior to jdk1.2, javac did not implement the spec.  Instead
            // it <em>always</em> set outer_class_info_index to the
            // enclosing outer class and if the class was anonymous,
            // it set inner_name_index to be the index of a CONSTANT_Utf8
            // entry containing the null string "" (idNull).  This code is
            // designed to handle either kind of class file.
            //
            // See also the compileClass() method in SourceClass.java.

            // Read in the inner_class_info
            // InnerClasses_attribute.classes.inner_class_info_index
            int inner_index = ds.readUnsignedShort();
            // could check for zero.
            ClassDeclaration inner = cpool.getDeclaration(env, inner_index);

            // Read in the outer_class_info.  Note that the index will be
            // zero if the class is "not a member".
            ClassDeclaration outer = null;
            // InnerClasses_attribute.classes.outer_class_info_index
            int outer_index = ds.readUnsignedShort();
            if (outer_index != 0) {
                outer = cpool.getDeclaration(env, outer_index);
            }

            // Read in the inner_name_index.  This may be zero.  An anonymous
            // class will either have an inner_nm_index of zero (as the spec
            // dictates) or it will have an inner_nm of idNull (for classes
            // generated by pre-1.2 compilers).  Handle both.
            Identifier inner_nm = idNull;
            // InnerClasses_attribute.classes.inner_name_index
            int inner_nm_index = ds.readUnsignedShort();
            if (inner_nm_index != 0) {
                inner_nm = Identifier.lookup(cpool.getString(inner_nm_index));
            }

            // Read in the modifiers for the inner class.
            // InnerClasses_attribute.classes.inner_name_index
            int mods = ds.readUnsignedShort();

            // Is the class accessible?
            // The old code checked for
            //
            //    (!inner_nm.equals(idNull) && (mods & M_PRIVATE) == 0)
            //
            // which we will preserve to keep it working for class files
            // generated by 1.1 compilers.  In addition we check for
            //
            //    (outer != null)
            //
            // as an additional check that only makes sense with 1.2
            // generated files.  Note that it is entirely possible that
            // the M_PRIVATE bit is always enough.  We are being
            // conservative here.
            //
            // The ATT_ALLCLASSES flag causes the M_PRIVATE modifier
            // to be ignored, and is used by tools such as 'javap' that
            // wish to examine all classes regardless of the normal access
            // controls that apply during compilation.  Note that anonymous
            // and local classes are still not considered accessible, though
            // named local classes in jdk1.1 may slip through.  Note that
            // this accessibility test is an optimization, and it is safe to
            // err on the side of greater accessibility.
            boolean accessible =
                (outer != null) &&
                (!inner_nm.equals(idNull)) &&
                ((mods & M_PRIVATE) == 0 ||
                 (flags & ATT_ALLCLASSES) != 0);

            // The reader should note that there has been a significant change
            // in the way that the InnerClasses attribute is being handled.
            // In particular, previously the compiler called initInner() for
            // <em>every</em> inner class.  Now the compiler does not call
            // initInner() if the inner class is inaccessible.  This means
            // that inaccessible inner classes don't have any of the processing
            // from initInner() done for them: fixing the access flags,
            // setting outerClass, setting outerMember in their outerClass,
            // etc.  We believe this is fine: if the class is inaccessible
            // and binary, then everyone who needs to see its internals
            // has already been compiled.  Hopefully.

            if (accessible) {
                Identifier nm =
                    Identifier.lookupInner(outer.getName(), inner_nm);

                // Tell the type module about the nesting relation:
                Type.tClass(nm);

                if (inner.equals(getClassDeclaration())) {
                    // The inner class in the record is this class.
                    try {
                        ClassDefinition outerClass = outer.getClassDefinition(env);
                        initInner(outerClass, mods);
                    } catch (ClassNotFound e) {
                        // report the error elsewhere
                    }
                } else if (outer.equals(getClassDeclaration())) {
                    // The outer class in the record is this class.
                    try {
                        ClassDefinition innerClass =
                            inner.getClassDefinition(env);
                        initOuter(innerClass, mods);
                    } catch (ClassNotFound e) {
                        // report the error elsewhere
                    }
                }
            }
        }
    }

    private void initInner(ClassDefinition outerClass, int mods) {
        if (getOuterClass() != null)
            return;             // already done
        /******
        // Maybe set static, protected, or private.
        if ((modifiers & M_PUBLIC) != 0)
            mods &= M_STATIC;
        else
            mods &= M_PRIVATE | M_PROTECTED | M_STATIC;
        modifiers |= mods;
        ******/
        // For an inner class, the class access may have been weakened
        // from that originally declared the source.  We must take the
        // actual access permissions against which we check any source
        // we are currently compiling from the InnerClasses attribute.
        // We attempt to guard here against bogus combinations of modifiers.
        if ((mods & M_PRIVATE) != 0) {
            // Private cannot be combined with public or protected.
            mods &= ~(M_PUBLIC | M_PROTECTED);
        } else if ((mods & M_PROTECTED) != 0) {
            // Protected cannot be combined with public.
            mods &= ~M_PUBLIC;
        }
        if ((mods & M_INTERFACE) != 0) {
            // All interfaces are implicitly abstract.
            // All interfaces that are members of a type are implicitly static.
            mods |= (M_ABSTRACT | M_STATIC);
        }
        if (outerClass.isInterface()) {
            // All types that are members of interfaces are implicitly
            // public and static.
            mods |= (M_PUBLIC | M_STATIC);
            mods &= ~(M_PRIVATE | M_PROTECTED);
        }
        modifiers = mods;

        setOuterClass(outerClass);

        for (MemberDefinition field = getFirstMember();
             field != null;
             field = field.getNextMember()) {
            if (field.isUplevelValue()
                    && outerClass.getType().equals(field.getType())
                    && field.getName().toString().startsWith(prefixThis)) {
                setOuterMember(field);
            }
        }
    }

    private void initOuter(ClassDefinition innerClass, int mods) {
        if (innerClass instanceof BinaryClass)
            ((BinaryClass)innerClass).initInner(this, mods);
        addMember(new BinaryMember(innerClass));
    }

    /**
     * Write the class out to a given stream.  This function mirrors the loader.
     */
    public void write(Environment env, OutputStream out) throws IOException {
        DataOutputStream data = new DataOutputStream(out);

        // write out the header
        data.writeInt(JAVA_MAGIC);
        data.writeShort(env.getMinorVersion());
        data.writeShort(env.getMajorVersion());

        // Write out the constant pool
        cpool.write(data, env);

        // Write class information
        data.writeShort(getModifiers() & ACCM_CLASS);
        data.writeShort(cpool.indexObject(getClassDeclaration(), env));
        data.writeShort((getSuperClass() != null)
                        ? cpool.indexObject(getSuperClass(), env) : 0);
        data.writeShort(interfaces.length);
        for (int i = 0 ; i < interfaces.length ; i++) {
            data.writeShort(cpool.indexObject(interfaces[i], env));
        }

        // count the fields and the methods
        int fieldCount = 0, methodCount = 0;
        for (MemberDefinition f = firstMember; f != null; f = f.getNextMember())
            if (f.isMethod()) methodCount++; else fieldCount++;

        // write out each the field count, and then each field
        data.writeShort(fieldCount);
        for (MemberDefinition f = firstMember; f != null; f = f.getNextMember()) {
            if (!f.isMethod()) {
                data.writeShort(f.getModifiers() & ACCM_FIELD);
                String name = f.getName().toString();
                String signature = f.getType().getTypeSignature();
                data.writeShort(cpool.indexString(name, env));
                data.writeShort(cpool.indexString(signature, env));
                BinaryAttribute.write(((BinaryMember)f).atts, data, cpool, env);
            }
        }

        // write out each method count, and then each method
        data.writeShort(methodCount);
        for (MemberDefinition f = firstMember; f != null; f = f.getNextMember()) {
            if (f.isMethod()) {
                data.writeShort(f.getModifiers() & ACCM_METHOD);
                String name = f.getName().toString();
                String signature = f.getType().getTypeSignature();
                data.writeShort(cpool.indexString(name, env));
                data.writeShort(cpool.indexString(signature, env));
                BinaryAttribute.write(((BinaryMember)f).atts, data, cpool, env);
            }
        }

        // write out the class attributes
        BinaryAttribute.write(atts, data, cpool, env);
        data.flush();
    }

    /**
     * Get the dependencies
     */
    public Enumeration getDependencies() {
        return dependencies.elements();
    }

    /**
     * Add a dependency
     */
    public void addDependency(ClassDeclaration c) {
        if ((c != null) && !dependencies.contains(c)) {
            dependencies.addElement(c);
        }
    }

    /**
     * Get the constant pool
     */
    public BinaryConstantPool getConstants() {
        return cpool;
    }

    /**
     * Get a class attribute
     */
    public byte getAttribute(Identifier name)[] {
        for (BinaryAttribute att = atts ; att != null ; att = att.next) {
            if (att.name.equals(name)) {
                return att.data;
            }
        }
        return null;
    }
}
