/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.testing.tests.performance.java;

import java.lang.reflect.*;
import java.security.AccessController;

import org.eclipse.persistence.Version;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
import org.eclipse.persistence.internal.security.PrivilegedGetClassLoaderForClass;
import org.eclipse.persistence.internal.security.PrivilegedGetConstructorFor;
import org.eclipse.persistence.internal.security.PrivilegedGetContextClassLoader;
import org.eclipse.persistence.internal.security.PrivilegedGetDeclaredConstructorFor;
import org.eclipse.persistence.internal.security.PrivilegedGetDeclaredField;
import org.eclipse.persistence.internal.security.PrivilegedGetFields;
import org.eclipse.persistence.internal.security.PrivilegedGetMethod;
import org.eclipse.persistence.internal.security.PrivilegedGetMethodParameterTypes;
import org.eclipse.persistence.internal.security.PrivilegedGetMethodReturnType;
import org.eclipse.persistence.internal.security.PrivilegedGetValueFromField;
import org.eclipse.persistence.internal.security.PrivilegedInvokeConstructor;
import org.eclipse.persistence.internal.security.PrivilegedMethodInvoker;
import org.eclipse.persistence.internal.security.PrivilegedNewInstanceFromClass;
import org.eclipse.persistence.internal.security.PrivilegedSetValueInField;
import org.eclipse.persistence.testing.framework.*;

/**
 * This test compares the performance for
 * 1. Direct calls - Baseline
 * 2. doPrivileged actions in org.eclipse.persistence.internal.security.PriviledgedAccessController
 * 3. Bypassing doPrivileged actions in org.eclipse.persistence.internal.security.PriviledgedAccessController
 */
public class DoPrivilegedTest extends PerformanceComparisonTestCase {
    public DoPrivilegedTest() {
        setName("Direct calls vs. doPrivileged vs. Bypassing doPrivileged PerformanceComparisonTest");
        setDescription("This test compares the performance for doPrivileged.");

        // check TopLink and OC4j doPrivileged flag.
        String usePrivileged = System.getProperty("eclipselink.security.usedoprivileged");
        if ((System.getSecurityManager() == null) || ((usePrivileged == null) || usePrivileged.equalsIgnoreCase("false"))) {
            addBypassDoPrivilegedTest();
        } else {
            addDoPrivilegedTest();
        }
    }

    /**
     * Direct calls
     */
    @Override
    public void test() throws Exception {
        String className = "org.eclipse.persistence.Version";
        String fieldName = "buildNumber";
        String fieldValue = "TopLink Blah";
        String methodName = "setProduct";

        Class<?> clazz = null;
        Version version = null;
        Method method = null;
        try {
            clazz = Class.forName(className);
            Class<?>[] methodParameterTypes = { Class.forName("java.lang.String") };
            ClassLoader clazzloader = clazz.getClassLoader();
            ClassLoader classloader = Thread.currentThread().getContextClassLoader();
            Class.forName(className, true, clazzloader);
            version = (Version)clazz.getConstructor().newInstance();

            Field[] fields = clazz.getFields();
            Field field = getDeclaredField(clazz, fieldName, true);
            try {
                int intValueFromField = field.getInt(version);
            } catch (Exception e) {
            }
            field.get(version);
            try {
                field.set(version, fieldValue);
            } catch (Exception e) {
            }

            String lineSeparator = System.getProperty("file.separator");

            method = getDeclaredMethod(clazz, methodName, methodParameterTypes, true);
            method.getParameterTypes();
            method.getReturnType();
            Object[] parameters = { "TopLink Blah." };
            method.invoke(version, parameters);

            Constructor constructor = clazz.getConstructor((Class<?>[])null);
            constructor.setAccessible(true);
            Constructor declaredConstructor = clazz.getDeclaredConstructor((Class<?>[])null);
            declaredConstructor.setAccessible(true);
            constructor.newInstance((Object[])null);

            //                    new XMLSessionConfigLoader().loadInternal(new SessionManager(), clazzloader, false, false);
        } catch (Exception e) {
            throw (new TestProblemException("An exception has been caught."));
        }
    }

    /**
     * doPrivileged
     */
    public void addDoPrivilegedTest() {
        PerformanceComparisonTestCase test = new PerformanceComparisonTestCase() {
            @Override
            public void test() {
                testDoPrivileged();
            }
        };
        test.setName("DoPrivilegedTest");
        test.setAllowableDecrease(-35);
        addTest(test);
    }

    /**
     * Bypassing doPrivileged
     */
    public void addBypassDoPrivilegedTest() {
        PerformanceComparisonTestCase test = new PerformanceComparisonTestCase() {
            @Override
            public void test() {
                testDoPrivileged();
            }
        };
        test.setName("BypassDoPrivilegedTest");
        test.setAllowableDecrease(-10);
        addTest(test);
    }

    public void testDoPrivileged() {
        String className = "org.eclipse.persistence.Version";
        String fieldName = "product";
        String fieldValue = "TopLink Blah";
        String methodName = "setProduct";

        Class<?> clazz = null;
        Version version = null;
        Method method = null;
        try {
            clazz = AccessController.doPrivileged(new PrivilegedClassForName<>(className));
            Class<?>[] methodParameterTypes = { AccessController.doPrivileged(new PrivilegedClassForName<>("java.lang.String")) };
            ClassLoader clazzloader = AccessController.doPrivileged(new PrivilegedGetClassLoaderForClass(clazz));
            ClassLoader classloader = AccessController.doPrivileged(new PrivilegedGetContextClassLoader(Thread.currentThread()));
            AccessController.doPrivileged(new PrivilegedClassForName<>(className, true, clazzloader));
            version = (Version)AccessController.doPrivileged(new PrivilegedNewInstanceFromClass<>(clazz));

            Field[] fields = AccessController.doPrivileged(new PrivilegedGetFields(clazz));
            Field field = AccessController.doPrivileged(new PrivilegedGetDeclaredField(clazz, fieldName, true));
            try {
                int intValueFromField = (Integer) AccessController.doPrivileged(new PrivilegedGetValueFromField(field, version));
            } catch (Exception e) {
            }
            AccessController.doPrivileged(new PrivilegedGetValueFromField(field, version));
            try {
                AccessController.doPrivileged(new PrivilegedSetValueInField(field, version, fieldValue));
            } catch (Exception e) {
            }

            String lineSeparator = PrivilegedAccessHelper.getLineSeparator();

            method = AccessController.doPrivileged(new PrivilegedGetMethod(clazz, methodName, methodParameterTypes, true));
            AccessController.doPrivileged(new PrivilegedGetMethodParameterTypes(method));
            AccessController.doPrivileged(new PrivilegedGetMethodReturnType(method));
            Object[] parameters = { "TopLink Blah." };
            AccessController.doPrivileged(new PrivilegedMethodInvoker(method, version, parameters));

            Constructor<?> constructor = AccessController.doPrivileged(new PrivilegedGetConstructorFor<>(clazz, null, true));
            Constructor declaredConstructor = AccessController.doPrivileged(new PrivilegedGetDeclaredConstructorFor(clazz, null, true));
            AccessController.doPrivileged(new PrivilegedInvokeConstructor(constructor, null));

            //                    PrivilegedAccessController.loadDeploymentXML(new XMLSessionConfigLoader(),new SessionManager(), clazzloader, false, false);
        } catch (Exception e) {
            throw (new TestProblemException("An exception has been caught."));
        }
    }

    public Field getDeclaredField(final Class<?> javaClass, final String fieldName, final boolean shouldSetAccessible) throws NoSuchFieldException {
        Field field = findDeclaredField(javaClass, fieldName);
        if (shouldSetAccessible) {
            field.setAccessible(true);
        }
        return field;
    }

    public Method getDeclaredMethod(final Class<?> javaClass, final String methodName, final Class<?>[] methodParameterTypes, final boolean shouldSetAccessible) throws NoSuchMethodException {
        Method method = findDeclaredMethod(javaClass, methodName, methodParameterTypes);
        if (shouldSetAccessible) {
            method.setAccessible(true);
        }
        return method;
    }

    /**
     * Finding a field within a class potentially has to navigate through it's superclasses to eventually
     * find the field.  This method is called by the public getDeclaredField() method and does a recursive
     * search for the named field in the given classes or it's superclasses.
     */
    private Field findDeclaredField(Class<?> javaClass, String fieldName) throws NoSuchFieldException {
        try {
            return javaClass.getDeclaredField(fieldName);
        } catch (NoSuchFieldException ex) {
            Class<?> superclass = javaClass.getSuperclass();
            if (superclass == null) {
                throw ex;
            } else {
                return findDeclaredField(superclass, fieldName);
            }
        }
    }

    /**
     * Finding a method within a class potentially has to navigate through it's superclasses to eventually
     * find the method.  This method is called by the public getDeclaredMethod() method and does a recursive
     * search for the named method in the given classes or it's superclasses.
     */
    private Method findDeclaredMethod(Class<?> javaClass, String methodName, Class<?>[] methodParameterTypes) throws NoSuchMethodException {
        try {
            return javaClass.getDeclaredMethod(methodName, methodParameterTypes);
        } catch (NoSuchMethodException ex) {
            Class<?> superclass = javaClass.getSuperclass();
            if (superclass == null) {
                throw ex;
            } else {
                return findDeclaredMethod(superclass, methodName, methodParameterTypes);
            }
        }
    }
}
