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

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedActionException;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.core.descriptors.CoreInstantiationPolicy;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
import org.eclipse.persistence.internal.security.PrivilegedGetDeclaredConstructorFor;
import org.eclipse.persistence.internal.security.PrivilegedInvokeConstructor;
import org.eclipse.persistence.internal.security.PrivilegedMethodInvoker;
import org.eclipse.persistence.internal.sessions.AbstractSession;

/**
 * <b>Purpose</b>: Allows customization of how an object is created/instantiated.<p>
 *
 * So, here is how it works:<p>
 *
 * If there is no method specified<br>
 *     - all the other settings are ignored and<br>
 *     - the descriptor class's default constructor is invoked.<br>
 * If a factory is specified<br>
 *     - the factoryClass and factoryClassMethod are ignored and<br>
 *     - the method is invoked on the factory.<br>
 * If neither a factory nor a factoryClass are specified<br>
 *     - the factoryClassMethod is ignored and<br>
 *     - the method is invoked on the descriptor class (as a static).<br>
 * If only the factoryClass is specified<br>
 *     - the factory is created by invoking the factoryClass' default (zero-argument) constructor and<br>
 *     - the method is invoked on the resulting factory.<br>
 * If both the factoryClass and the factoryClassMethod are specified<br>
 *     - the factory is created by invoking the factoryClassMethod on the factoryClass (as a static) and<br>
 *     - the method is invoked on the resulting factory.<p>
 *
 * The only thing we can't support in the current configuration is invoking a static on some,
 * client-specified, factoryClass to build new instances of the descriptor class; and it's debatable
 * whether that is desirable...<p>
 *
 * It might be reasonable to rework this into a number of different classes that implement
 * an interface...
 */
public class InstantiationPolicy extends CoreInstantiationPolicy implements Cloneable, Serializable {

    /**
     * The method invoked on either the descriptor class (in which case it is static) or
     * the factory (in which case it is not static) to build a new instance of the descriptor class.
     */
    protected String methodName;

    /** The method is resolved during initialization, and it is not serialized. */
    protected transient Method method;

    /**
     * The class of the factory. The factory is instantiated by either invoking this class's default
     * (zero-argument) constructor or the factoryMethod specified below.
     */
    protected Class factoryClass;
    protected String factoryClassName;

    /**
     * Static method invoked on the factoryClass to get the factory instance. If this is null, the
     * factory class's default (zero-argument) constructor is invoked.
     */
    protected String factoryMethodName;

    /**
     * The object factory. This can be specified directly by the client, or it can be built dynamically
     * using the the factoryClass and, optionally, the factoryMethodName.
     */
    protected Object factory;

    /** Backpointer to descriptor. */
    protected ClassDescriptor descriptor;

    /** Must be transient because java.lang.Constructor is not serializable. */
    private transient Constructor defaultConstructor;

    /**
     * Default constructor
     */
    public InstantiationPolicy() {
        super();
    }

    /**
     * Build and return a new instance, using the appropriate mechanism.
     */
    @Override
    public Object buildNewInstance() throws DescriptorException {
        // PERF: Just check method-name.
        if (this.methodName == null) {
            return buildNewInstanceUsingDefaultConstructor();
        } else {
            return buildNewInstanceUsingFactory();
        }
    }

    /**
     * Build and return a new instance, using the default (zero-argument) constructor.
     */
    protected Object buildNewInstanceUsingDefaultConstructor() throws DescriptorException {
        try {
            if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                try {
                    return AccessController.doPrivileged(new PrivilegedInvokeConstructor(getDefaultConstructor(), null));
                } catch (PrivilegedActionException exception) {
                    Exception throwableException = exception.getException();
                    if (throwableException instanceof InvocationTargetException){
                        throw DescriptorException.targetInvocationWhileConstructorInstantiation(getDescriptor(), throwableException);
                    } else if (throwableException instanceof IllegalAccessException){
                        throw DescriptorException.illegalAccessWhileConstructorInstantiation(getDescriptor(), throwableException);
                    } else {
                        throw DescriptorException.instantiationWhileConstructorInstantiation(getDescriptor(), throwableException);
                    }
                 }
            } else {
                // PERF: Check lazy init with null check.
                if (this.defaultConstructor == null) {
                    getDefaultConstructor();
                }
                return this.defaultConstructor.newInstance((Object[])null);
            }
        } catch (InvocationTargetException exception) {
            throw DescriptorException.targetInvocationWhileConstructorInstantiation(getDescriptor(), exception);
        } catch (IllegalAccessException exception) {
            throw DescriptorException.illegalAccessWhileConstructorInstantiation(getDescriptor(), exception);
        } catch (InstantiationException exception) {
            throw DescriptorException.instantiationWhileConstructorInstantiation(getDescriptor(), exception);
        } catch (NoSuchMethodError exception) {
            // This exception is not documented but gets thrown.
            throw DescriptorException.noSuchMethodWhileConstructorInstantiation(getDescriptor(), exception);
        } catch (NullPointerException exception) {
            // Some JVMs will throw a NULL pointer exception here
            throw DescriptorException.nullPointerWhileConstructorInstantiation(getDescriptor(), exception);
        }
    }

    /**
     * Build and return a new instance, using the factory.
     * The factory can be null, in which case the method is a static method defined by the descriptor class.
     */
    protected Object buildNewInstanceUsingFactory() throws DescriptorException {
        try {
            // If the method is static, the first argument is ignored and can be null
            if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                try {
                    return AccessController.doPrivileged(new PrivilegedMethodInvoker(getMethod(), getFactory(), new Object[0]));
                } catch (PrivilegedActionException exception) {
                    Exception throwableException = exception.getException();
                    if (throwableException instanceof IllegalAccessException) {
                        throw DescriptorException.illegalAccessWhileMethodInstantiation(getMethod().toString(), this.getDescriptor(), throwableException);
                    } else {
                        throw DescriptorException.targetInvocationWhileMethodInstantiation(getMethod().toString(), this.getDescriptor(), throwableException);
                    }
                }
            } else {
                return PrivilegedAccessHelper.invokeMethod(getMethod(), getFactory(), new Object[0]);
            }
        } catch (IllegalAccessException exception) {
            throw DescriptorException.illegalAccessWhileMethodInstantiation(getMethod().toString(), this.getDescriptor(), exception);
        } catch (InvocationTargetException exception) {
            throw DescriptorException.targetInvocationWhileMethodInstantiation(getMethod().toString(), this.getDescriptor(), exception);
        } catch (NullPointerException exception) {
            // Some JVMs will throw a NULL pointer exception here
            throw DescriptorException.nullPointerWhileMethodInstantiation(this.getMethod().toString(), this.getDescriptor(), exception);
        }
    }

    /**
     * INTERNAL:
     * Clones the InstantiationPolicy
     */
    @Override
    public Object clone() {
        try {
            // clones itself
            return super.clone();
        } catch (Exception exception) {
            throw new AssertionError(exception);
        }
    }

    /**
     * Return the default (zero-argument) constructor for the descriptor class.
     */
    protected Constructor getDefaultConstructor() throws DescriptorException {
        // Lazy initialize, because the constructor cannot be serialized
        if (defaultConstructor == null) {
            this.setDefaultConstructor(this.buildDefaultConstructor());
        }
        return defaultConstructor;
    }

    /**
     * Build and return the default (zero-argument) constructor for the descriptor class.
     */
    protected Constructor buildDefaultConstructor() throws DescriptorException {
        return this.buildDefaultConstructorFor(this.getDescriptor().getJavaClass());
    }

    /**
     * Build and return the default (zero-argument) constructor for the specified class.
     */
    protected Constructor buildDefaultConstructorFor(Class javaClass) throws DescriptorException {
        try {
            if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                try {
                    return AccessController.doPrivileged(new PrivilegedGetDeclaredConstructorFor(javaClass, new Class[0], true));
                } catch (PrivilegedActionException exception) {
                    throw DescriptorException.noSuchMethodWhileInitializingInstantiationPolicy(javaClass.getName() + ".<Default Constructor>", getDescriptor(), exception.getException());
                }
            } else {
                return PrivilegedAccessHelper.getDeclaredConstructorFor(javaClass, new Class[0], true);
            }
        } catch (NoSuchMethodException exception) {
            throw DescriptorException.noSuchMethodWhileInitializingInstantiationPolicy(javaClass.getName() + ".<Default Constructor>", getDescriptor(), exception);
        }
    }

    protected ClassDescriptor getDescriptor() {
        return descriptor;
    }

    public String getFactoryMethodName() {
        return factoryMethodName;
    }

    public Object getFactory() {
        return factory;
    }

    public Class getFactoryClass() {
        return factoryClass;
    }

    public String getFactoryClassName() {
        if ((factoryClassName == null) && (factoryClass != null)) {
            factoryClassName = factoryClass.getName();
        }
        return factoryClassName;
    }

    protected Method getMethod() {
        return method;
    }

    public String getMethodName() {
        return methodName;
    }

    /**
     * If necessary, initialize the factory and the method.
     */
    public void initialize(AbstractSession session) throws DescriptorException {
        if (this.isUsingDefaultConstructor()) {
            // May not have a constructor as may be abstract or interface so only lazy init.
            return;
        }
        try {
            this.initializeMethod();
            if (!(Modifier.isStatic(getMethod().getModifiers()))) {
                // If the factory has been specified directly, do not overwrite it
                if (this.getFactory() == null) {
                    this.setFactory(this.buildFactory());
                }
            }
        } catch (DescriptorException ex) {
            session.getIntegrityChecker().handleError(ex);
        }
    }

    protected Object buildFactory() throws DescriptorException {
        // If there is no factory class specified, there is no factory;
        // we will be using a static method defined by the descriptor class...
        if (this.getFactoryClass() == null) {
            return null;
        }

        // If there is a factory class specified but no factory method name,
        // instantiate the factory using the default constructor
        if (this.getFactoryMethodName() == null) {
            return this.buildFactoryUsingDefaultConstructor();
        }

        // If both the factory class and the factory method name have been specified,
        // instantiate the factory by invoking the static factory method
        return this.buildFactoryUsingStaticMethod();
    }

    /**
     * Build and return the factory, using its default constructor.
     */
    protected Object buildFactoryUsingDefaultConstructor() throws DescriptorException {
        try {
            if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                try {
                    return AccessController.doPrivileged(new PrivilegedInvokeConstructor(buildFactoryDefaultConstructor(), null));
                } catch (PrivilegedActionException exception) {
                    Exception throwableException = exception.getException();
                    if (throwableException instanceof InvocationTargetException){
                        throw DescriptorException.targetInvocationWhileConstructorInstantiationOfFactory(getDescriptor(), throwableException);
                    } else if (throwableException instanceof IllegalAccessException){
                        throw DescriptorException.illegalAccessWhileConstructorInstantiationOfFactory(getDescriptor(), throwableException);
                    } else {
                        throw DescriptorException.instantiationWhileConstructorInstantiationOfFactory(getDescriptor(), throwableException);
                    }
                 }
            } else {
                return PrivilegedAccessHelper.invokeConstructor(buildFactoryDefaultConstructor(), null);
            }
        } catch (InvocationTargetException exception) {
            throw DescriptorException.targetInvocationWhileConstructorInstantiationOfFactory(getDescriptor(), exception);
        } catch (IllegalAccessException exception) {
            throw DescriptorException.illegalAccessWhileConstructorInstantiationOfFactory(getDescriptor(), exception);
        } catch (InstantiationException exception) {
            throw DescriptorException.instantiationWhileConstructorInstantiationOfFactory(getDescriptor(), exception);
        } catch (NoSuchMethodError exception) {
            // This exception is not documented but gets thrown.
            throw DescriptorException.noSuchMethodWhileConstructorInstantiationOfFactory(getDescriptor(), exception);
        } catch (NullPointerException exception) {
            // Some JVMs will throw a NULL pointer exception here
            throw DescriptorException.nullPointerWhileConstructorInstantiationOfFactory(getDescriptor(), exception);
        }
    }

    /**
     * Build and return the default (zero-argument) constructor for the factory class.
     */
    protected Constructor buildFactoryDefaultConstructor() throws DescriptorException {
        return this.buildDefaultConstructorFor(this.getFactoryClass());
    }

    /**
     * Build and return the factory, using the specified static method.
     */
    protected Object buildFactoryUsingStaticMethod() throws DescriptorException {
        Method factoryMethod = this.buildMethod(this.getFactoryClass(), this.getFactoryMethodName(), new Class[0]);

        try {
            // it should be static and zero-argument...
            if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                try {
                    return AccessController.doPrivileged(new PrivilegedMethodInvoker(factoryMethod, null, null));
                } catch (PrivilegedActionException exception) {
                    Exception throwableException = exception.getException();
                    if (throwableException instanceof IllegalAccessException) {
                        throw DescriptorException.illegalAccessWhileMethodInstantiationOfFactory(getFactoryMethodName(), getDescriptor(), throwableException);
                    } else {
                        throw DescriptorException.targetInvocationWhileMethodInstantiationOfFactory(getFactoryMethodName(), getDescriptor(), throwableException);
                    }

                }
            } else {
                return PrivilegedAccessHelper.invokeMethod(factoryMethod, null, null);
            }
        } catch (IllegalAccessException exception) {
            throw DescriptorException.illegalAccessWhileMethodInstantiationOfFactory(getFactoryMethodName(), getDescriptor(), exception);
        } catch (InvocationTargetException exception) {
            throw DescriptorException.targetInvocationWhileMethodInstantiationOfFactory(getFactoryMethodName(), getDescriptor(), exception);
        } catch (NullPointerException exception) {
            // Some JVMs will throw a NULL pointer exception here
            throw DescriptorException.nullPointerWhileMethodInstantiationOfFactory(getFactoryMethodName(), getDescriptor(), exception);
        }
    }

    /**
     * Initialize the method.
     * It is either a static on the descriptor class, or it is a non-static on the factory.
     */
    protected void initializeMethod() throws DescriptorException {
        Class tempClass;
        if (this.getFactory() != null) {
            tempClass = this.getFactory().getClass();
        } else if (this.getFactoryClass() == null) {
            tempClass = this.getDescriptor().getJavaClass();
        } else {
            tempClass = this.getFactoryClass();
        }
        this.setMethod(this.buildMethod(tempClass, this.getMethodName(), new Class[0]));
    }

    /**
     * Build the specified method.
     */
    protected Method buildMethod(Class methodClass, String methodName, Class[] methodParameterTypes) throws DescriptorException {
        try {
            return Helper.getDeclaredMethod(methodClass, methodName, methodParameterTypes);
        } catch (NoSuchMethodException exception) {
            throw DescriptorException.noSuchMethodWhileInitializingInstantiationPolicy(methodClass.getName() + "." + methodName, this.getDescriptor(), exception);
        } catch (SecurityException exception) {
            throw DescriptorException.securityWhileInitializingInstantiationPolicy(methodClass.getName() + "." + methodName, this.getDescriptor(), exception);
        }
    }

    /**
     * If no method name is specified, they we have to use the default (zero-argument) constructor.
     */
    public boolean isUsingDefaultConstructor() {
        return this.getMethodName() == null;
    }

    protected void setDefaultConstructor(Constructor defaultConstructor) {
        this.defaultConstructor = defaultConstructor;
    }

    public void setDescriptor(ClassDescriptor descriptor) {
        this.descriptor = descriptor;
    }

    protected void setFactoryMethodName(String factoryMethodName) {
        this.factoryMethodName = factoryMethodName;
    }

    protected void setFactory(Object factory) {
        this.factory = factory;
    }

    protected void setFactoryClass(Class factoryClass) {
        this.factoryClass = factoryClass;
    }

    protected void setFactoryClassName(String factoryClassName) {
        this.factoryClassName = factoryClassName;
    }

    protected void setMethod(Method method) {
        this.method = method;
    }

    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }

    /**
     * INTERNAL:
     * Convert all the class-name-based settings in this InstantiationPolicy to actual class-based
     * settings.  This method is used when converting a project that has been built
     * with class names to a project with classes.
     */
    public void convertClassNamesToClasses(ClassLoader classLoader){
        if (factoryClassName == null){
            return;
        }
        Class factoryClass = null;
        try{
            if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                try {
                    factoryClass = AccessController.doPrivileged(new PrivilegedClassForName(factoryClassName, true, classLoader));
                } catch (PrivilegedActionException exception) {
                    throw ValidationException.classNotFoundWhileConvertingClassNames(factoryClassName, exception.getException());
                }
            } else {
                factoryClass = org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(factoryClassName, true, classLoader);
            }
        } catch (ClassNotFoundException exc){
            throw ValidationException.classNotFoundWhileConvertingClassNames(factoryClassName, exc);
        }
        setFactoryClass(factoryClass);
    }


    @Override
    public String toString() {
        String mName = null;
        if (this.isUsingDefaultConstructor()) {
            mName = "<CONSTRUCTOR>";
        } else {
            mName = this.getMethodName();
        }
        return Helper.getShortClassName(this) + "(" + mName + ")";
    }

    public void useDefaultConstructorInstantiationPolicy() {
        setMethodName(null);
        setFactory(null);
        setFactoryClass(null);
        setFactoryClassName(null);
        setFactoryMethodName(null);
    }

    public void useFactoryInstantiationPolicy(Class factoryClass, String methodName) {
        setMethodName(methodName);
        setFactory(null);
        setFactoryClass(factoryClass);
        setFactoryClassName(factoryClass.getName());
        setFactoryMethodName(null);
    }

    public void useFactoryInstantiationPolicy(Class factoryClass, String methodName, String factoryMethodName) {
        setMethodName(methodName);
        setFactory(null);
        setFactoryClass(factoryClass);
        setFactoryClassName(factoryClass.getName());
        setFactoryMethodName(factoryMethodName);
    }

    @Override
    public void useFactoryInstantiationPolicy(String factoryClassName, String methodName) {
        setMethodName(methodName);
        setFactory(null);
        setFactoryClass(null);
        setFactoryClassName(factoryClassName);
        setFactoryMethodName(null);
    }

    public void useFactoryInstantiationPolicy(String factoryClassName, String methodName, String factoryMethodName) {
        setMethodName(methodName);
        setFactory(null);
        setFactoryClass(null);
        setFactoryClassName(factoryClassName);
        setFactoryMethodName(factoryMethodName);
    }

    public void useFactoryInstantiationPolicy(Object factory, String methodName) {
        setMethodName(methodName);
        setFactory(factory);
        setFactoryClass(null);
        setFactoryClassName(null);
        setFactoryMethodName(null);
    }

    public void useMethodInstantiationPolicy(String staticMethodName) {
        setMethodName(staticMethodName);
        setFactory(null);
        setFactoryClass(null);
        setFactoryClassName(null);
        setFactoryMethodName(null);
    }
}
