/*
 * 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.util;

import proguard.classfile.*;
import proguard.classfile.attribute.*;
import proguard.classfile.attribute.visitor.*;
import proguard.classfile.constant.*;
import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.util.StringMatcher;

/**
 * This InstructionVisitor initializes any constant <code>Class.forName</code> or
 * <code>.class</code> references of all classes it visits. More specifically,
 * it fills out the references of string constant pool entries that refer to a
 * class in the program class pool or in the library class pool.
 * <p>
 * It optionally prints notes if on usage of
 * <code>(SomeClass)Class.forName(variable).newInstance()</code>.
 * <p>
 * The class hierarchy must be initialized before using this visitor.
 *
 * @see ClassSuperHierarchyInitializer
 *
 * @author Eric Lafortune
 */
public class DynamicClassReferenceInitializer
extends      SimplifiedVisitor
implements   InstructionVisitor,
             ConstantVisitor,
             AttributeVisitor
{
    public static final int X = InstructionSequenceMatcher.X;
    public static final int Y = InstructionSequenceMatcher.Y;
    public static final int Z = InstructionSequenceMatcher.Z;

    public static final int A = InstructionSequenceMatcher.A;
    public static final int B = InstructionSequenceMatcher.B;
    public static final int C = InstructionSequenceMatcher.C;
    public static final int D = InstructionSequenceMatcher.D;


    private final Constant[] CLASS_FOR_NAME_CONSTANTS = new Constant[]
    {
        // 0
        new MethodrefConstant(1, 2, null, null),
        new ClassConstant(3, null),
        new NameAndTypeConstant(4, 5),
        new Utf8Constant(ClassConstants.NAME_JAVA_LANG_CLASS),
        new Utf8Constant(ClassConstants.METHOD_NAME_CLASS_FOR_NAME),
        new Utf8Constant(ClassConstants.METHOD_TYPE_CLASS_FOR_NAME),

        // 6
        new MethodrefConstant(1, 7, null, null),
        new NameAndTypeConstant(8, 9),
        new Utf8Constant(ClassConstants.METHOD_NAME_NEW_INSTANCE),
        new Utf8Constant(ClassConstants.METHOD_TYPE_NEW_INSTANCE),

        // 10
        new MethodrefConstant(1, 11, null, null),
        new NameAndTypeConstant(12, 13),
        new Utf8Constant(ClassConstants.METHOD_NAME_CLASS_GET_COMPONENT_TYPE),
        new Utf8Constant(ClassConstants.METHOD_TYPE_CLASS_GET_COMPONENT_TYPE),
    };

    // Class.forName("SomeClass").
    private final Instruction[] CONSTANT_CLASS_FOR_NAME_INSTRUCTIONS = new Instruction[]
    {
        new ConstantInstruction(InstructionConstants.OP_LDC, X),
        new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0),
    };

    // (SomeClass)Class.forName(someName).newInstance().
    private final Instruction[] CLASS_FOR_NAME_CAST_INSTRUCTIONS = new Instruction[]
    {
        new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0),
        new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 6),
        new ConstantInstruction(InstructionConstants.OP_CHECKCAST, X),
    };


//    private Constant[] DOT_CLASS_JAVAC_CONSTANTS = new Constant[]
//    {
//        new MethodrefConstant(A, 1, null, null),
//        new NameAndTypeConstant(2, 3),
//        new Utf8Constant(ClassConstants.METHOD_NAME_DOT_CLASS_JAVAC),
//        new Utf8Constant(ClassConstants.METHOD_TYPE_DOT_CLASS_JAVAC),
//    };

    private final Constant[] DOT_CLASS_JAVAC_CONSTANTS = new Constant[]
    {
        new MethodrefConstant(A, 1, null, null),
        new NameAndTypeConstant(B, 2),
        new Utf8Constant(ClassConstants.METHOD_TYPE_DOT_CLASS_JAVAC),
    };

    // SomeClass.class = class$("SomeClass") (javac).
    private final Instruction[] DOT_CLASS_JAVAC_INSTRUCTIONS = new Instruction[]
    {
        new ConstantInstruction(InstructionConstants.OP_LDC, X),
        new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0),
    };


//    private Constant[] DOT_CLASS_JIKES_CONSTANTS = new Constant[]
//    {
//        new MethodrefConstant(A, 1, null, null),
//        new NameAndTypeConstant(2, 3),
//        new Utf8Constant(ClassConstants.METHOD_NAME_DOT_CLASS_JIKES),
//        new Utf8Constant(ClassConstants.METHOD_TYPE_DOT_CLASS_JIKES),
//    };

    private final Constant[] DOT_CLASS_JIKES_CONSTANTS = new Constant[]
    {
        new MethodrefConstant(A, 1, null, null),
        new NameAndTypeConstant(B, 2),
        new Utf8Constant(ClassConstants.METHOD_TYPE_DOT_CLASS_JIKES),
    };

    // SomeClass.class = class("SomeClass", false) (jikes).
    private final Instruction[] DOT_CLASS_JIKES_INSTRUCTIONS = new Instruction[]
    {
        new ConstantInstruction(InstructionConstants.OP_LDC, X),
        new SimpleInstruction(InstructionConstants.OP_ICONST_0),
        new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0),
    };

    // return Class.forName(v0).
    private final Instruction[] DOT_CLASS_JAVAC_IMPLEMENTATION_INSTRUCTIONS = new Instruction[]
    {
        new VariableInstruction(InstructionConstants.OP_ALOAD_0),
        new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0),
        new SimpleInstruction(InstructionConstants.OP_ARETURN),
    };

    // return Class.forName(v0), if (!v1) .getComponentType().
    private final Instruction[] DOT_CLASS_JIKES_IMPLEMENTATION_INSTRUCTIONS = new Instruction[]
    {
        new VariableInstruction(InstructionConstants.OP_ALOAD_0),
        new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0),
        new VariableInstruction(InstructionConstants.OP_ALOAD_1),
        new BranchInstruction(InstructionConstants.OP_IFNE, +6),
        new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 10),
        new SimpleInstruction(InstructionConstants.OP_ARETURN),
    };

    // return Class.forName(v0).getComponentType().
    private final Instruction[] DOT_CLASS_JIKES_IMPLEMENTATION_INSTRUCTIONS2 = new Instruction[]
    {
        new VariableInstruction(InstructionConstants.OP_ALOAD_0),
        new ConstantInstruction(InstructionConstants.OP_INVOKESTATIC, 0),
        new ConstantInstruction(InstructionConstants.OP_INVOKEVIRTUAL, 10),
        new SimpleInstruction(InstructionConstants.OP_ARETURN),
    };


    private final ClassPool      programClassPool;
    private final ClassPool      libraryClassPool;
    private final WarningPrinter missingNotePrinter;
    private final WarningPrinter dependencyWarningPrinter;
    private final WarningPrinter notePrinter;
    private final StringMatcher  noteExceptionMatcher;


    private final InstructionSequenceMatcher constantClassForNameMatcher =
        new InstructionSequenceMatcher(CLASS_FOR_NAME_CONSTANTS,
                                       CONSTANT_CLASS_FOR_NAME_INSTRUCTIONS);

    private final InstructionSequenceMatcher classForNameCastMatcher =
        new InstructionSequenceMatcher(CLASS_FOR_NAME_CONSTANTS,
                                       CLASS_FOR_NAME_CAST_INSTRUCTIONS);

    private final InstructionSequenceMatcher dotClassJavacMatcher =
        new InstructionSequenceMatcher(DOT_CLASS_JAVAC_CONSTANTS,
                                       DOT_CLASS_JAVAC_INSTRUCTIONS);

    private final InstructionSequenceMatcher dotClassJikesMatcher =
        new InstructionSequenceMatcher(DOT_CLASS_JIKES_CONSTANTS,
                                       DOT_CLASS_JIKES_INSTRUCTIONS);

    private final InstructionSequenceMatcher dotClassJavacImplementationMatcher =
        new InstructionSequenceMatcher(CLASS_FOR_NAME_CONSTANTS,
                                       DOT_CLASS_JAVAC_IMPLEMENTATION_INSTRUCTIONS);

    private final InstructionSequenceMatcher dotClassJikesImplementationMatcher =
        new InstructionSequenceMatcher(CLASS_FOR_NAME_CONSTANTS,
                                       DOT_CLASS_JIKES_IMPLEMENTATION_INSTRUCTIONS);

    private final InstructionSequenceMatcher dotClassJikesImplementationMatcher2 =
        new InstructionSequenceMatcher(CLASS_FOR_NAME_CONSTANTS,
                                       DOT_CLASS_JIKES_IMPLEMENTATION_INSTRUCTIONS2);


    // A field acting as a return variable for the visitors.
    private boolean isClassForNameInvocation;


    /**
     * Creates a new DynamicClassReferenceInitializer that optionally prints
     * warnings and notes, with optional class specifications for which never
     * to print notes.
     */
    public DynamicClassReferenceInitializer(ClassPool      programClassPool,
                                            ClassPool      libraryClassPool,
                                            WarningPrinter missingNotePrinter,
                                            WarningPrinter dependencyWarningPrinter,
                                            WarningPrinter notePrinter,
                                            StringMatcher  noteExceptionMatcher)
    {
        this.programClassPool         = programClassPool;
        this.libraryClassPool         = libraryClassPool;
        this.missingNotePrinter       = missingNotePrinter;
        this.dependencyWarningPrinter = dependencyWarningPrinter;
        this.notePrinter              = notePrinter;
        this.noteExceptionMatcher     = noteExceptionMatcher;
    }


    // Implementations for InstructionVisitor.

    public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
    {
        // Try to match the (SomeClass)Class.forName(someName).newInstance()
        // construct. Apply this matcher first, so the next matcher can still
        // reset it after the first instruction.
        instruction.accept(clazz, method, codeAttribute, offset,
                           classForNameCastMatcher);

        // Did we find a match?
        if (classForNameCastMatcher.isMatching())
        {
            // Print out a note about the construct.
            clazz.constantPoolEntryAccept(classForNameCastMatcher.matchedConstantIndex(X), this);
        }

        // Try to match the Class.forName("SomeClass") construct.
        instruction.accept(clazz, method, codeAttribute, offset,
                           constantClassForNameMatcher);

        // Did we find a match?
        if (constantClassForNameMatcher.isMatching())
        {
            // Fill out the matched string constant.
            clazz.constantPoolEntryAccept(constantClassForNameMatcher.matchedConstantIndex(X), this);

            // Don't look for the dynamic construct.
            classForNameCastMatcher.reset();
        }

        // Try to match the javac .class construct.
        instruction.accept(clazz, method, codeAttribute, offset,
                           dotClassJavacMatcher);

        // Did we find a match?
        if (dotClassJavacMatcher.isMatching() &&
            isDotClassMethodref(clazz, dotClassJavacMatcher.matchedConstantIndex(0)))
        {
            // Fill out the matched string constant.
            clazz.constantPoolEntryAccept(dotClassJavacMatcher.matchedConstantIndex(X), this);
        }

        // Try to match the jikes .class construct.
        instruction.accept(clazz, method, codeAttribute, offset,
                           dotClassJikesMatcher);

        // Did we find a match?
        if (dotClassJikesMatcher.isMatching() &&
            isDotClassMethodref(clazz, dotClassJikesMatcher.matchedConstantIndex(0)))
        {
            // Fill out the matched string constant.
            clazz.constantPoolEntryAccept(dotClassJikesMatcher.matchedConstantIndex(X), this);
        }
    }


    // Implementations for ConstantVisitor.

    /**
     * Fills out the link to the referenced class.
     */
    public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
    {
        // Save a reference to the corresponding class.
        String externalClassName = stringConstant.getString(clazz);
        String internalClassName = ClassUtil.internalClassName(
                                   ClassUtil.externalBaseType(externalClassName));

        stringConstant.referencedClass = findClass(clazz.getName(), internalClassName);
    }


    /**
     * Prints out a note about the class cast to this class, if applicable.
     */
    public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
    {
        // Print out a note about the class cast.
        if (noteExceptionMatcher == null ||
            !noteExceptionMatcher.matches(classConstant.getName(clazz)))
        {
            notePrinter.print(clazz.getName(),
                              classConstant.getName(clazz),
                              "Note: " +
                              ClassUtil.externalClassName(clazz.getName()) +
                              " calls '(" +
                              ClassUtil.externalClassName(classConstant.getName(clazz)) +
                              ")Class.forName(variable).newInstance()'");
        }
    }


    /**
     * Checks whether the referenced method is a .class method.
     */
    public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
    {
        String methodType = methodrefConstant.getType(clazz);

        // Do the method's class and type match?
        if (methodType.equals(ClassConstants.METHOD_TYPE_DOT_CLASS_JAVAC) ||
            methodType.equals(ClassConstants.METHOD_TYPE_DOT_CLASS_JIKES))
        {
            String methodName = methodrefConstant.getName(clazz);

            // Does the method's name match one of the special names?
            isClassForNameInvocation =
                methodName.equals(ClassConstants.METHOD_NAME_DOT_CLASS_JAVAC) ||
                methodName.equals(ClassConstants.METHOD_NAME_DOT_CLASS_JIKES);

            if (isClassForNameInvocation)
            {
                return;
            }

            String className = methodrefConstant.getClassName(clazz);

            // Note that we look for the class by name, since the referenced
            // class has not been initialized yet.
            Clazz referencedClass = programClassPool.getClass(className);
            if (referencedClass != null)
            {
                // Check if the code of the referenced method is .class code.
                // Note that we look for the method by name and type, since the
                // referenced method has not been initialized yet.
                referencedClass.methodAccept(methodName,
                                             methodType,
                                             new AllAttributeVisitor(this));
            }
        }
    }


    // Implementations for AttributeVisitor.

    public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}


    public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
    {
        // Check whether this is class$(String), as generated by javac, or
        // class(String, boolean), as generated by jikes, or an optimized
        // version.
        isClassForNameInvocation =
            isDotClassMethodCode(clazz, method, codeAttribute,
                                 dotClassJavacImplementationMatcher, 5)  ||
            isDotClassMethodCode(clazz, method, codeAttribute,
                                 dotClassJikesImplementationMatcher, 12) ||
            isDotClassMethodCode(clazz, method, codeAttribute,
                                 dotClassJikesImplementationMatcher2, 8);
    }


    // Small utility methods.

    /**
     * Returns whether the given method reference corresponds to a .class
     * method, as generated by javac or by jikes.
     */
    private boolean isDotClassMethodref(Clazz clazz, int methodrefConstantIndex)
    {
        isClassForNameInvocation = false;

        // Check if the code of the referenced method is .class code.
        clazz.constantPoolEntryAccept(methodrefConstantIndex, this);

        return isClassForNameInvocation;
    }


    /**
     * Returns whether the first whether the first instructions of the
     * given code attribute match with the given instruction matcher.
     */
    private boolean isDotClassMethodCode(Clazz                      clazz,
                                         Method                     method,
                                         CodeAttribute              codeAttribute,
                                         InstructionSequenceMatcher codeMatcher,
                                         int                        codeLength)
    {
        // Check the minimum code length.
        if (codeAttribute.u4codeLength < codeLength)
        {
            return false;
        }

        // Check the actual instructions.
        codeMatcher.reset();
        codeAttribute.instructionsAccept(clazz, method, 0, codeLength, codeMatcher);
        return codeMatcher.isMatching();
    }


    /**
     * Returns the class with the given name, either for the program class pool
     * or from the library class pool, or <code>null</code> if it can't be found.
     */
    private Clazz findClass(String referencingClassName, String name)
    {
        // Is it an array type?
        if (ClassUtil.isInternalArrayType(name))
        {
            // Ignore any primitive array types.
            if (!ClassUtil.isInternalClassType(name))
            {
                return null;
            }

            // Strip the array part.
            name = ClassUtil.internalClassNameFromClassType(name);
        }

        // First look for the class in the program class pool.
        Clazz clazz = programClassPool.getClass(name);

        // Otherwise look for the class in the library class pool.
        if (clazz == null)
        {
            clazz = libraryClassPool.getClass(name);

            if (clazz == null &&
                missingNotePrinter != null)
            {
                // We didn't find the superclass or interface. Print a note.
                missingNotePrinter.print(referencingClassName,
                                         name,
                                         "Note: " +
                                         ClassUtil.externalClassName(referencingClassName) +
                                         ": can't find dynamically referenced class " +
                                         ClassUtil.externalClassName(name));
            }
        }
        else if (dependencyWarningPrinter != null)
        {
            // The superclass or interface was found in the program class pool.
            // Print a warning.
            dependencyWarningPrinter.print(referencingClassName,
                                           name,
                                           "Warning: library class " +
                                           ClassUtil.externalClassName(referencingClassName) +
                                           " depends dynamically on program class " +
                                           ClassUtil.externalClassName(name));
        }

        return clazz;
    }
}
