/*
 * Copyright (c) 2013, 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.
 */

/*
 * @test
 * @bug 8011805
 * @summary Update sun.tools.java class file reading/writing support to include the new constant pool entries (including invokedynamic)
 */

import java.io.DataInputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import sun.tools.java.ClassDeclaration;
import sun.tools.java.Identifier;
import sun.rmi.rmic.BatchEnvironment;

public class CFCTest {

    /* Constant table */
    private static final int CONSTANT_UTF8 = 1;
    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_CLASS = 7;
    private static final int CONSTANT_STRING = 8;
    private static final int CONSTANT_FIELD = 9;
    private static final int CONSTANT_METHOD = 10;
    private static final int CONSTANT_INTERFACEMETHOD = 11;
    private static final int CONSTANT_NAMEANDTYPE = 12;
    private static final int CONSTANT_METHODHANDLE = 15;
    private static final int CONSTANT_METHODTYPE = 16;
    private static final int CONSTANT_INVOKEDYNAMIC = 18;

    String testClassName = this.getClass().getCanonicalName();
    String testClassPath = System.getProperty("test.classes", ".");

    interface I {
        int get();
    }

    public static void main(String[] args) throws Exception {
        new CFCTest().testNewConstants();
    }

    void testNewConstants() throws Exception {
        // Presence of lambda causes new constant pool constant types to be used
        I lam = () -> 88;
        if (lam.get() == 88) {
            System.out.println("Sanity passed: Lambda worked.");
        } else {
            throw new RuntimeException("Sanity failed: bad lambda execution");
        }

        // Verify that all the new constant pool constant types are present
        String clsName = testClassPath + File.separator + testClassName + ".class";
        ClassConstantChecker ccc = new ClassConstantChecker(clsName);
        ccc.checkFound(CONSTANT_METHODHANDLE);
        ccc.checkFound(CONSTANT_METHODTYPE);
        ccc.checkFound(CONSTANT_INVOKEDYNAMIC);

        // Heart of test: read the class file with the new constant types
        exerciseClassDefinition();
        System.out.println("ClassDefinition read without failure.\n");
   }

    /**
     * Failure is seen when getClassDefinition causes class read
     */
    void exerciseClassDefinition() throws Exception {
        BatchEnvironment env = new BatchEnvironment(System.out,
                BatchEnvironment.createClassPath(testClassPath, null, null),
                null);
        try {
            ClassDeclaration decl = env.getClassDeclaration(
                    Identifier.lookup(testClassName));
            decl.getClassDefinition(env);
        } finally {
            env.flushErrors();
            env.shutdown();
        }
    }

    private class ClassConstantChecker {

        private DataInputStream in;
        private boolean[] found;

        ClassConstantChecker(String clsName) throws IOException {
            in = new DataInputStream(new FileInputStream(clsName));
            found = new boolean[CONSTANT_INVOKEDYNAMIC + 20];
            try {
                check();
            } finally {
                in.close();
            }
        }

        void checkFound(int tag) throws Exception {
            if (found[tag]) {
                System.out.printf("Constant pool tag found: %d\n", tag);
            } else {
                throw new RuntimeException("Insufficient test, constant pool tag NOT found: " + tag);
            }
        }

        private void skip(int n) throws IOException {
            if (in.skipBytes(n) != n) {
                throw new EOFException();
            }
        }

        private void check() throws IOException {
            skip(8); // magic, version
            int count = in.readUnsignedShort();
            for (int i = 1; i < count; i++) {
                int j = i;
                // JVM 4.4 cp_info.tag
                int tag = in.readByte();
                found[tag] = true;
                switch (tag) {
                    case CONSTANT_UTF8:
                        in.readUTF();
                        break;
                    case CONSTANT_LONG:
                    case CONSTANT_DOUBLE:
                        skip(8);
                        break;
                    case CONSTANT_CLASS:
                    case CONSTANT_STRING:
                        skip(2);
                        break;
                    case CONSTANT_INTEGER:
                    case CONSTANT_FLOAT:
                    case CONSTANT_FIELD:
                    case CONSTANT_METHOD:
                    case CONSTANT_INTERFACEMETHOD:
                    case CONSTANT_NAMEANDTYPE:
                        skip(4);
                        break;

                    case CONSTANT_METHODHANDLE:
                        skip(3);
                        break;
                    case CONSTANT_METHODTYPE:
                        skip(2);
                        break;
                    case CONSTANT_INVOKEDYNAMIC:
                        skip(4);
                        break;

                    case 0:
                    default:
                        throw new ClassFormatError("invalid constant type: " + tag);
                }
            }
        }
    }
}
