/*
 * Copyright (c) 2018, 2021, 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 8196830 8235351 8257874
 * @modules java.base/jdk.internal.reflect
 * @run testng/othervm CallerSensitiveAccess
 * @summary Check Lookup findVirtual, findStatic and unreflect behavior with
 *          caller sensitive methods with focus on AccessibleObject.setAccessible
 */

import java.io.IOException;
import java.io.UncheckedIOException;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.lang.module.ModuleReader;
import java.lang.module.ModuleReference;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.InaccessibleObjectException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.List;
import java.util.StringJoiner;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import jdk.internal.reflect.CallerSensitive;

import org.testng.annotations.DataProvider;
import org.testng.annotations.NoInjection;
import org.testng.annotations.Test;
import static org.testng.Assert.*;

public class CallerSensitiveAccess {

    /**
     * Caller sensitive methods in APIs exported by java.base.
     */
    @DataProvider(name = "callerSensitiveMethods")
    static Object[][] callerSensitiveMethods() {
        try (Stream<Method> stream = callerSensitiveMethods(Object.class.getModule())) {
            return stream.map(m -> new Object[]{m, shortDescription(m)})
                    .toArray(Object[][]::new);
        }
    }

    /**
     * Using publicLookup, attempt to use findVirtual or findStatic to obtain a
     * method handle to a caller sensitive method.
     */
    @Test(dataProvider = "callerSensitiveMethods",
            expectedExceptions = IllegalAccessException.class)
    public void testPublicLookupFind(@NoInjection Method method, String desc) throws Exception {
        Lookup lookup = MethodHandles.publicLookup();
        Class<?> refc = method.getDeclaringClass();
        String name = method.getName();
        MethodType mt = MethodType.methodType(method.getReturnType(), method.getParameterTypes());
        if (Modifier.isStatic(method.getModifiers())) {
            lookup.findStatic(refc, name, mt);
        } else {
            lookup.findVirtual(refc, name, mt);
        }
    }

    /**
     * Using publicLookup, attempt to use unreflect to obtain a method handle to a
     * caller sensitive method.
     */
    @Test(dataProvider = "callerSensitiveMethods",
            expectedExceptions = IllegalAccessException.class)
    public void testPublicLookupUnreflect(@NoInjection Method method, String desc) throws Exception {
        MethodHandles.publicLookup().unreflect(method);
    }

    /**
     * public accessible caller sensitive methods in APIs exported by java.base.
     */
    @DataProvider(name = "accessibleCallerSensitiveMethods")
    static Object[][] accessibleCallerSensitiveMethods() {
        try (Stream<Method> stream = callerSensitiveMethods(Object.class.getModule())) {
            return stream
                .filter(m -> Modifier.isPublic(m.getModifiers()))
                .map(m -> { m.setAccessible(true); return m; })
                .map(m -> new Object[] { m, shortDescription(m) })
                .toArray(Object[][]::new);
        }
    }

    /**
     * Using publicLookup, attempt to use unreflect to obtain a method handle to a
     * caller sensitive method.
     */
    @Test(dataProvider = "accessibleCallerSensitiveMethods",
            expectedExceptions = IllegalAccessException.class)
    public void testLookupUnreflect(@NoInjection Method method, String desc) throws Exception {
        MethodHandles.publicLookup().unreflect(method);
    }

    /**
     * Using a Lookup with no original access that can't lookup caller-sensitive
     * method
     */
    @Test(dataProvider = "callerSensitiveMethods",
            expectedExceptions = IllegalAccessException.class)
    public void testLookupNoOriginalAccessFind(@NoInjection Method method, String desc) throws Exception {
        Lookup lookup = MethodHandles.lookup().dropLookupMode(Lookup.ORIGINAL);
        assertTrue(lookup.hasFullPrivilegeAccess());
        Class<?> refc = method.getDeclaringClass();
        String name = method.getName();
        MethodType mt = MethodType.methodType(method.getReturnType(), method.getParameterTypes());
        if (Modifier.isStatic(method.getModifiers())) {
            lookup.findStatic(refc, name, mt);
        } else {
            lookup.findVirtual(refc, name, mt);
        }
    }

    /**
     * Using a Lookup with no original access that can't unreflect caller-sensitive
     * method
     */
    @Test(dataProvider = "callerSensitiveMethods",
            expectedExceptions = IllegalAccessException.class)
    public void testLookupNoOriginalAccessUnreflect(@NoInjection Method method, String desc) throws Exception {
        Lookup lookup = MethodHandles.lookup().dropLookupMode(Lookup.ORIGINAL);
        assertTrue(lookup.hasFullPrivilegeAccess());
        lookup.unreflect(method);
    }

    // -- Test method handles to setAccessible --

    private int aField;

    Field accessibleField() {
        try {
            return getClass().getDeclaredField("aField");
        } catch (NoSuchFieldException e) {
            fail();
            return null;
        }
    }

    Field inaccessibleField() {
        try {
            return String.class.getDeclaredField("hash");
        } catch (NoSuchFieldException e) {
            fail();
            return null;
        }
    }

    void findAndInvokeSetAccessible(Class<? extends AccessibleObject> refc, Field f) throws Throwable {
        MethodType mt = MethodType.methodType(void.class, boolean.class);
        MethodHandle mh = MethodHandles.lookup().findVirtual(refc, "setAccessible", mt);
        mh.invoke(f, true);  // may throw InaccessibleObjectException
        assertTrue(f.isAccessible());
    }

    void unreflectAndInvokeSetAccessible(Method m, Field f) throws Throwable {
        assertTrue(m.getName().equals("setAccessible"));
        assertFalse(Modifier.isStatic(m.getModifiers()));
        MethodHandle mh = MethodHandles.lookup().unreflect(m);
        mh.invoke(f, true);   // may throw InaccessibleObjectException
        assertTrue(f.isAccessible());
    }

    /**
     * Create a method handle to setAccessible and use it to suppress access to an
     * accessible member.
     */
    @Test
    public void testSetAccessible1() throws Throwable {
        findAndInvokeSetAccessible(AccessibleObject.class, accessibleField());
    }
    @Test
    public void testSetAccessible2() throws Throwable {
        findAndInvokeSetAccessible(Field.class, accessibleField());
    }
    @Test
    public void testSetAccessible3() throws Throwable {
        Method m = AccessibleObject.class.getMethod("setAccessible", boolean.class);
        unreflectAndInvokeSetAccessible(m, accessibleField());
    }
    @Test
    public void testSetAccessible4() throws Throwable {
        Method m = Field.class.getMethod("setAccessible", boolean.class);
        unreflectAndInvokeSetAccessible(m, accessibleField());
    }

    /**
     * Create a method handle to setAccessible and attempt to use it to suppress
     * access to an inaccessible member.
     */
    @Test(expectedExceptions = InaccessibleObjectException.class)
    public void testSetAccessible5() throws Throwable {
        findAndInvokeSetAccessible(AccessibleObject.class, inaccessibleField());
    }
    @Test(expectedExceptions = InaccessibleObjectException.class)
    public void testSetAccessible6() throws Throwable {
        findAndInvokeSetAccessible(Field.class, inaccessibleField());
    }
    @Test(expectedExceptions = InaccessibleObjectException.class)
    public void testSetAccessible7() throws Throwable {
        Method m = AccessibleObject.class.getMethod("setAccessible", boolean.class);
        unreflectAndInvokeSetAccessible(m, inaccessibleField());
    }
    @Test(expectedExceptions = InaccessibleObjectException.class)
    public void testSetAccessible8() throws Throwable {
        Method m = Field.class.getMethod("setAccessible", boolean.class);
        unreflectAndInvokeSetAccessible(m, inaccessibleField());
    }


    // -- Test sub-classes of AccessibleObject --

    /**
     * Custom AccessibleObject objects. One class overrides setAccessible, the other
     * does not override this method.
     */
    @DataProvider(name = "customAccessibleObjects")
    static Object[][] customAccessibleObjectClasses() {
        return new Object[][] { { new S1() }, { new S2() } };
    }
    public static class S1 extends AccessibleObject { }
    public static class S2 extends AccessibleObject {
        @Override
        public void setAccessible(boolean flag) {
            super.setAccessible(flag);
        }
    }

    void findAndInvokeSetAccessible(Lookup lookup, AccessibleObject obj) throws Throwable {
        MethodType mt = MethodType.methodType(void.class, boolean.class);
        MethodHandle mh = lookup.findVirtual(obj.getClass(), "setAccessible", mt);
        mh.invoke(obj, true);
        assertTrue(obj.isAccessible());
    }

    void unreflectAndInvokeSetAccessible(Lookup lookup, AccessibleObject obj) throws Throwable {
        Method m = obj.getClass().getMethod("setAccessible", boolean.class);
        MethodHandle mh = lookup.unreflect(m);
        mh.invoke(obj, true);
        assertTrue(obj.isAccessible());
    }

    /**
     * Using publicLookup, create a method handle to setAccessible and invoke it
     * on a custom AccessibleObject object.
     */
    @Test(expectedExceptions = IllegalAccessException.class)
    public void testPublicLookupSubclass1() throws Throwable {
        // S1 does not override setAccessible
        findAndInvokeSetAccessible(MethodHandles.publicLookup(), new S1());
    }
    @Test
    public void testPublicLookupSubclass2() throws Throwable {
        // S2 overrides setAccessible
        findAndInvokeSetAccessible(MethodHandles.publicLookup(), new S2());
    }
    @Test(expectedExceptions = IllegalAccessException.class)
    public void testPublicLookupSubclass3() throws Throwable {
        // S1 does not override setAccessible
        unreflectAndInvokeSetAccessible(MethodHandles.publicLookup(), new S1());
    }
    @Test
    public void testPublicLookupSubclass4() throws Throwable {
        // S2 overrides setAccessible
        unreflectAndInvokeSetAccessible(MethodHandles.publicLookup(), new S2());
    }

    /**
     * Using a full power lookup, create a method handle to setAccessible and
     * invoke it on a custom AccessibleObject object.
     */
    @Test(dataProvider = "customAccessibleObjects")
    public void testLookupSubclass1(AccessibleObject obj) throws Throwable {
        findAndInvokeSetAccessible(MethodHandles.lookup(), obj);
    }
    @Test(dataProvider = "customAccessibleObjects")
    public void testLookupSubclass2(AccessibleObject obj) throws Throwable {
        unreflectAndInvokeSetAccessible(MethodHandles.lookup(), obj);
    }

    /**
     * Using a full power lookup, create a method handle to setAccessible on a
     * sub-class of AccessibleObject and then attempt to invoke it on a Field object.
     */
    @Test(dataProvider = "customAccessibleObjects",
            expectedExceptions = ClassCastException.class)
    public void testLookupSubclass3(AccessibleObject obj) throws Throwable {
        MethodType mt = MethodType.methodType(void.class, boolean.class);
        Lookup lookup = MethodHandles.lookup();
        MethodHandle mh = lookup.findVirtual(obj.getClass(), "setAccessible", mt);
        mh.invoke(accessibleField(), true);  // should throw ClassCastException
    }

    /**
     * Using a full power lookup, use unreflect to create a method handle to
     * setAccessible on a sub-class of AccessibleObject, then attempt to invoke
     * it on a Field object.
     */
    @Test
    public void testLookupSubclass4() throws Throwable {
        // S1 does not override setAccessible
        Method m = S1.class.getMethod("setAccessible", boolean.class);
        assertTrue(m.getDeclaringClass() == AccessibleObject.class);
        MethodHandle mh = MethodHandles.lookup().unreflect(m);
        Field f = accessibleField();
        mh.invoke(f, true);
        assertTrue(f.isAccessible());
    }
    @Test(expectedExceptions = InaccessibleObjectException.class)
    public void testLookupSubclass5() throws Throwable {
        // S1 does not override setAccessible
        Method m = S1.class.getMethod("setAccessible", boolean.class);
        assertTrue(m.getDeclaringClass() == AccessibleObject.class);
        MethodHandle mh = MethodHandles.lookup().unreflect(m);
        mh.invoke(inaccessibleField(), true);  // should throw InaccessibleObjectException
    }
    @Test(expectedExceptions = ClassCastException.class)
    public void testLookupSubclass6() throws Throwable {
        // S2 overrides setAccessible
        Method m = S2.class.getMethod("setAccessible", boolean.class);
        assertTrue(m.getDeclaringClass() == S2.class);
        MethodHandle mh = MethodHandles.lookup().unreflect(m);
        mh.invoke(accessibleField(), true);  // should throw ClassCastException
    }
    @Test(expectedExceptions = ClassCastException.class)
    public void testLookupSubclass7() throws Throwable {
        // S2 overrides setAccessible
        Method m = S2.class.getMethod("setAccessible", boolean.class);
        assertTrue(m.getDeclaringClass() == S2.class);
        MethodHandle mh = MethodHandles.lookup().unreflect(m);
        mh.invoke(inaccessibleField(), true);  // should throw ClassCastException
    }

    /**
     * Field::getInt and Field::setInt are caller-sensitive methods.
     * Test access to private field.
     */
    private static int privateField = 0;
    @Test
    public void testPrivateField() throws Throwable {
        Field f = CallerSensitiveAccess.class.getDeclaredField("privateField");
        // Field::setInt
        MethodType mtype = MethodType.methodType(void.class, Object.class, int.class);
        MethodHandle mh = MethodHandles.lookup().findVirtual(Field.class, "setInt", mtype);
        mh.invokeExact(f, (Object)null, 5);
        // Field::getInt
        mh = MethodHandles.lookup().findVirtual(Field.class, "getInt", MethodType.methodType(int.class, Object.class));
        int value = (int)mh.invokeExact(f, (Object)null);
        assertTrue(value == 5);
    }

    private static class Inner {
        private static boolean privateField = false;
    }

    @Test
    public void testInnerPrivateField() throws Throwable {
        Field f = Inner.class.getDeclaredField("privateField");
        // Field::setInt
        MethodType mtype = MethodType.methodType(void.class, Object.class, boolean.class);
        MethodHandle mh = MethodHandles.lookup().findVirtual(Field.class, "setBoolean", mtype);
        mh.invokeExact(f, (Object)null, true);
        // Field::getInt
        mh = MethodHandles.lookup().findVirtual(Field.class, "getBoolean", MethodType.methodType(boolean.class, Object.class));
        boolean value = (boolean)mh.invokeExact(f, (Object)null);
        assertTrue(value);
    }

    // -- supporting methods --

    /**
     * Returns a stream of all caller sensitive methods on public classes in packages
     * exported by a named module.
     */
    static Stream<Method> callerSensitiveMethods(Module module) {
        assert module.isNamed();
        ModuleReference mref = module.getLayer().configuration()
                .findModule(module.getName())
                .orElseThrow(() -> new RuntimeException())
                .reference();
        // find all ".class" resources in the module
        // transform the resource name to a class name
        // load every class in the exported packages
        // return the caller sensitive methods of the public classes
        try (ModuleReader reader = mref.open()) {
            return reader.list()
                    .filter(rn -> rn.endsWith(".class"))
                    .map(rn -> rn.substring(0, rn.length() - 6)
                                 .replace('/', '.'))
                    .filter(cn -> module.isExported(packageName(cn)))
                    .map(cn -> Class.forName(module, cn))
                    .filter(refc -> refc != null
                                    && Modifier.isPublic(refc.getModifiers()))
                    .map(refc -> callerSensitiveMethods(refc))
                    .flatMap(List::stream);
        } catch (IOException ioe) {
            throw new UncheckedIOException(ioe);
        }
    }

    static String packageName(String cn) {
        int last = cn.lastIndexOf('.');
        if (last > 0) {
            return cn.substring(0, last);
        } else {
            return "";
        }
    }

    /**
     * Returns a list of the caller sensitive methods directly declared by the given
     * class.
     */
    static List<Method> callerSensitiveMethods(Class<?> refc) {
        return Arrays.stream(refc.getDeclaredMethods())
                .filter(m -> m.isAnnotationPresent(CallerSensitive.class))
                .collect(Collectors.toList());
    }

    /**
     * Returns a short description of the given method for tracing purposes.
     */
    static String shortDescription(Method m) {
        var sb = new StringBuilder();
        sb.append(m.getDeclaringClass().getName());
        sb.append('.');
        sb.append(m.getName());
        sb.append('(');
        StringJoiner sj = new StringJoiner(",");
        for (Class<?> parameterType : m.getParameterTypes()) {
            sj.add(parameterType.getTypeName());
        }
        sb.append(sj);
        sb.append(')');
        return sb.toString();
    }
}
