/*
 * Copyright (c) 2015, 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:
//     Marcel Valovy - 2.6 - initial implementation
package org.eclipse.persistence.jaxb;

import java.security.CodeSource;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;

import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import jakarta.validation.Path;
import jakarta.validation.Validation;
import jakarta.validation.ValidationException;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import jakarta.validation.groups.Default;

import org.eclipse.persistence.exceptions.BeanValidationException;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings;
import org.eclipse.persistence.logging.DefaultSessionLog;
import org.eclipse.persistence.logging.SessionLog;

/**
 * INTERNAL:
 *
 * JAXB Bean Validator. Serves three purposes:
 *  1. Determines if the validation callback should take place on the (un)marshal call.
 *  2. Processes the validation.
 *  3. Stores the constraintViolations from the last validation call.
 *
 * @author Marcel Valovy - marcel.valovy@oracle.com
 * @since 2.6
 */
class JAXBBeanValidator {

    /**
     * Represents the Default validation group. Storing it in constant saves resources.
     */
    static final Class<?>[] DEFAULT_GROUP_ARRAY = new Class<?>[] { Default.class };

    /**
     * Represents the difference between words 'marshalling' and 'unmarshalling';
     */
    private static final String PREFIX_UNMARSHALLING = "un";

    /**
     * Prevents endless invocation loops between unmarshaller - validator - unmarshaller.
     * Only used / needed in case {@link #noOptimisation} is {@code true}.
     */
    private static final ReentrantLock lock = new ReentrantLock();

    /**
     * Disable optimisations that skip bean validation processes on non-constrained objects.
     */
    private boolean noOptimisation = false;

    /**
     * Stores {@link #PREFIX_UNMARSHALLING} if this instance belongs to
     * {@link org.eclipse.persistence.jaxb.JAXBUnmarshaller}, otherwise stores empty String.
     */
    private final String prefix;

    /**
     * Reference to {@link org.eclipse.persistence.jaxb.JAXBContext}. Allows for callbacks.
     */
    private final JAXBContext context;

    /**
     * Stores the {@link jakarta.validation.Validator} implementation. Once found, the reference is preserved.
     */
    private Validator validator;

    /**
     * Stores constraint violations returned by last call to {@link jakarta.validation.Validator#validate(Object, Class[])}.
     * <p>After each {@link #validate(Object, Class[])} call, the reference is replaced.
     */
    private Set<ConstraintViolation<Object>> constraintViolations = Collections.emptySet();

    /**
     * Computed value saying if the validation can proceed under current conditions, represented by:
     * <blockquote><pre>
     *     - {@link #beanValidationMode}
     *     - {@link jakarta.validation.Validator} implementation present on classpath
     * </pre></blockquote>
     * <p>
     * Value is recomputed only on {@link #changeInternalState()} call.
     */
    private boolean canValidate;

    /**
     * Represents a state where {@link #beanValidationMode} mode is set to
     * {@link org.eclipse.persistence.jaxb.BeanValidationMode#AUTO} and BV implementation could not be found.
     */
    private boolean stopSearchingForValidator;

    /**
     * This field will usually be {@code null}. However, user may pass his own instance of
     * {@link jakarta.validation.ValidatorFactory} to
     * {@link #shouldValidate}() method, and it will be assigned to this field.
     * <p>
     * If not null, {@link #validator} field will be assigned only by calling method
     * {@link jakarta.validation.ValidatorFactory#getValidator()} the instance assigned to this field.
     */
    private ValidatorFactory validatorFactory;

    /**
     * Setting initial value to "NONE" will not trigger internalStateChange() when validation is off and save resources.
     */
    private BeanValidationMode beanValidationMode = BeanValidationMode.NONE;

    // Local logger instance.
    private final SessionLog log = new DefaultSessionLog();

    /**
     * Private constructor. Only to be called by factory methods.
     * @param prefix differentiates between marshaller and unmarshaller during logging
     * @param context jaxb context reference
     */
    private JAXBBeanValidator(String prefix, JAXBContext context) {
        this.prefix = prefix;
        this.context = context;
    }

    /**
     * Factory method.
     * <p>
     * The only difference between this method and {@link #getUnmarshallingBeanValidator} is not having
     * {@link #PREFIX_UNMARSHALLING} in String messages constructed for exceptions.
     *
     * @param context jaxb context reference
     * @return
     *          a new instance of {@link JAXBBeanValidator}.
     */
    static JAXBBeanValidator getMarshallingBeanValidator(JAXBContext context){
        return new JAXBBeanValidator("", context);
    }

    /**
     * Factory method.
     * <p>
     * The only difference between this method and {@link #getMarshallingBeanValidator} is having
     * {@link #PREFIX_UNMARSHALLING} in String messages constructed for exceptions.
     *
     * @param context jaxb context reference
     * @return
     *          a new instance of {@link JAXBBeanValidator}.
     */
    static JAXBBeanValidator getUnmarshallingBeanValidator(JAXBContext context){
        return new JAXBBeanValidator(PREFIX_UNMARSHALLING, context);
    }

    /**
     * PUBLIC:
     *
     * First, if validation has not been turned off before, check if passed value is constrained.
     *
     * Second, depending on Bean Validation Mode, either returns false or tries to initialize Validator:
     *  - AUTO tries to initialize Validator:
     *          returns true if succeeds, else false.
     *  - CALLBACK tries to initialize Validator:
     *          returns true if succeeds, else throws {@link BeanValidationException#providerNotFound}.
     *  - NONE returns false;
     *
     * BeanValidationMode is fetched from (un)marshaller upon each call.
     * If change in mode is detected, the internal state of the JAXBBeanValidator will be switched.
     *
     * Third, analyses the value and determines whether validation may be skipped.
     *
     * @param beanValidationMode Bean validation mode - allowed values AUTO, CALLBACK, NONE.
     * @param value validated object. It is passed because validation on some objects may be skipped,
     *              e.g. non-constrained objects (like XmlBindings).
     * @param preferredValidatorFactory Must be {@link ValidatorFactory} or null. Will use this factory as the
     *                                  preferred provider; if null, will use javax defaults.
     * @param noOptimisation if true, bean validation optimisations that skip non-constrained objects will not be
     *                       performed
     * @return
     *          true if should proceed with validation, else false.
     * @throws BeanValidationException
     *  {@link BeanValidationException#illegalValidationMode} or {@link BeanValidationException#providerNotFound}.
     * @since 2.6
     */
    boolean shouldValidate (Object value, BeanValidationMode beanValidationMode,
                            Object preferredValidatorFactory,
                            boolean noOptimisation) throws BeanValidationException {

        if (isValidationEffectivelyOff(beanValidationMode)) return false;

        this.noOptimisation = noOptimisation;

        if (!isConstrainedObject(value)) return false;

        /* Mode or validator factory was changed externally (or it's the first time this method is called). */
        if (this.beanValidationMode != beanValidationMode || this.validatorFactory != preferredValidatorFactory) {
            this.beanValidationMode = beanValidationMode;
            this.validatorFactory = (ValidatorFactory)preferredValidatorFactory;
            changeInternalState();
        }

        /* Is Validation implementation ready to validate. */
        return canValidate;
    }

    /**
     * Check if validation is effectively off, i.e. it was previously attempted to turn it on, but that failed.
     * @param beanValidationMode user passed beanValidationMode
     * @return true if validation is effectively off
     */
    private boolean isValidationEffectivelyOff(BeanValidationMode beanValidationMode) {
        return !  ((beanValidationMode == BeanValidationMode.AUTO && canValidate) /* most common case */
                || (beanValidationMode == BeanValidationMode.CALLBACK)
                /* beanValidationMode is AUTO but canValidate is yet to be resolved */
                || (beanValidationMode != BeanValidationMode.NONE && beanValidationMode != this.beanValidationMode)
        );
    }

    /**
     * Check if object contains any bean validation constraints or custom validation constraints.
     * @param value object
     * @return true if the object is not null and is constrained
     */
    private boolean isConstrainedObject(Object value) {
        /* Json is allowed to pass a null root object. Avoid NPE & speed things up. */
        if (value == null) return false;

        if (noOptimisation) {
            /* Stops the endless invocation loop which may occur when calling
             * Validation#buildDefaultValidatorFactory in a case when the user sets
             * custom validation configuration through "validation.xml" file and
             * the validation implementation tries to unmarshal the file with MOXy. */
            if (lock.isHeldByCurrentThread()) return false;

            /* Do not validate XmlBindings. */
            return !(value instanceof XmlBindings);
        }

        /* Ensure that the class contains BV annotations. If not, skip validation & speed things up.
         * note: This also effectively skips XmlBindings. */
        return context.getBeanValidationHelper().isConstrained(value.getClass());
    }

    /**
     * INTERNAL:
     *
     * Validates the value, as per BV spec.
     * Stores the result of validation in {@link #constraintViolations}.
     *
     * @param value Object to be validated.
     * @param groups Target groups as per BV spec. If null {@link #DEFAULT_GROUP_ARRAY} is used.
     */
    void validate(Object value, Class<?>... groups) throws BeanValidationException {
        Class<?>[] grp = groups;
        if (grp == null || grp.length == 0) {
            grp = DEFAULT_GROUP_ARRAY;
        }
        constraintViolations = validator.validate(value, grp);
        if (!constraintViolations.isEmpty())
            throw buildConstraintViolationException();
    }

    /**
     * @return constraintViolations from the last {@link #validate} call.
     */
    Set<ConstraintViolationWrapper<Object>> getConstraintViolations() {
        Set<ConstraintViolationWrapper<Object>> result = new HashSet<>(constraintViolations.size());
        for (ConstraintViolation<Object> cv : constraintViolations) {
            result.add(new ConstraintViolationWrapper<>(cv));
        }
        return result;
    }

    /**
     * INTERNAL:
     *
     * Puts variables to states which conform to the internal state machine.
     *
     * Internal states:
     *  Mode/Field Value          | NONE        | AUTO         | CALLBACK
     *  --------------------------|-------------|--------------|--------------
     *  canValidate               | false       | true/false   | true/false
     *  stopSearchingForValidator | false       | true/false   | false
     *  constraintViolations      | EmptySet    | n/a          | n/a
     *
     *  n/a ... value is not altered.
     *
     * @throws BeanValidationException illegalValidationMode or providerNotFound
     */
    private void changeInternalState() throws BeanValidationException {
        stopSearchingForValidator = false; // Reset the switch.
        switch (beanValidationMode) {
        case NONE:
            canValidate = false;
            constraintViolations = Collections.emptySet(); // Clear the reference from previous (un)marshal calls.
            break;
        case CALLBACK:
        case AUTO:
            canValidate = initValidator();
            break;
        default:
            throw BeanValidationException.illegalValidationMode(prefix, beanValidationMode.toString());
        }
    }

    /**
     * PUBLIC:
     *
     * Initializes validator if not already initialized.
     * If mode is BeanValidationMode.AUTO, then after an unsuccessful try to
     * initialize a Validator, property {@code stopSearchingForValidator} will be set to true.
     *
     * NOTE: Property {@code stopSearchingForValidator} can be reset only by triggering
     * {@link #changeInternalState}.
     *
     * @return {@code true} if validator initialization succeeded, otherwise {@code false}.
     * @throws BeanValidationException
     *              throws {@link org.eclipse.persistence.exceptions.BeanValidationException#PROVIDER_NOT_FOUND}
     */
    private boolean initValidator() throws BeanValidationException {
        if (validator == null && !stopSearchingForValidator){
            try {
                ValidatorFactory factory = getValidatorFactory();
                validator = factory.getValidator();
                printValidatorInfo();
            } catch (ValidationException ve) {
                if (beanValidationMode == BeanValidationMode.CALLBACK){
                    /* The following line ensures that changeInternalState() will be the
                     triggered on next (un)marshalling trials if mode is still CALLBACK.
                      That will ensure searching for Validator implementation again. */
                    beanValidationMode = BeanValidationMode.AUTO;
                    throw BeanValidationException.providerNotFound(prefix, ve);
                } else { // mode AUTO
                    stopSearchingForValidator = true; // Will not try to initialize validator on next tries.
                }
            }
        }
        return validator != null;
    }

    /**
     * INTERNAL:
     *
     * @return Preferred ValidatorFactory if set, else {@link Validation#buildDefaultValidatorFactory()}.
     */
    private ValidatorFactory getValidatorFactory() {
        if (validatorFactory != null) {
            return validatorFactory;
        }

        if (noOptimisation) {
            lock.lock();
            try {
                return Validation.buildDefaultValidatorFactory();
            } finally {
                lock.unlock();
            }
        }

        return Validation.buildDefaultValidatorFactory();
    }

    /**
     * INTERNAL:
     *
     * Builds ConstraintViolationException with constraintViolations, but no message.
     * Builds BeanValidationException with fully descriptive message, containing
     * the ConstraintViolationException.
     *
     * @return BeanValidationException, containing ConstraintViolationException.
     */
    private BeanValidationException buildConstraintViolationException() {
        ConstraintViolationException cve = new ConstraintViolationException(
                /* Do not remove the cast. */ constraintViolations);
        return BeanValidationException.constraintViolation(createConstraintViolationExceptionArgs(), cve);
    }

    /**
     * INTERNAL:
     * Builds an Object array containing args for ConstraintViolationException constructor.
     *
     * @return  [0] - prefix,
     *          [1] - rootBean (on what object the validation failed),
     *          [2] - linkedList of violatedConstraints, with overriden toString() for better formatting.
     */
    private Object[] createConstraintViolationExceptionArgs() {
        Object[] args = new Object[3];
        Iterator<? extends ConstraintViolation<?>> iterator = constraintViolations.iterator();
        assert iterator.hasNext(); // this method is to be called only if constraints violations are not empty
        ConstraintViolation<?> cv = iterator.next();
        Collection<ConstraintViolationInfo> violatedConstraints = new LinkedList<>() {
            @Override
            public String toString() {
                Iterator<ConstraintViolationInfo> it = iterator();
                StringBuilder sb = new StringBuilder();
                while (it.hasNext())
                    sb.append("\n-->").append(it.next().toString());
                return sb.toString();
            }
        };
        args[0] = prefix;
        Object bean = cv.getRootBean();
        // NOTE:
        // 1. Do not use bean.toString(), it could leak secure information.
        // 2. And use identityHashCode, for these reasons:
        //      - prevents NPE which could be caused by a poorly implemented hashCode
        //      - serves as a better mean of identification of the bean.
        args[1] = bean.getClass().toString().substring("class ".length())
                + "@" + Integer.toHexString(System.identityHashCode(bean));
        args[2] = violatedConstraints;
        for (;;) {
            violatedConstraints.add(new ConstraintViolationInfo(cv.getMessage(), cv.getPropertyPath()));
            if (iterator.hasNext()) cv = iterator.next();
            else break;
        }
        return args;
    }

    /**
     * Logs the name of underlying validation impl jar used. Only logs once per context to avoid log cluttering.
     * To be called after successful assignment of validator.
     */
    private void printValidatorInfo() {
        if (!context.getHasLoggedValidatorInfo().getAndSet(true)) {
            CodeSource validationImplJar = getValidatorCodeSource();
            if (log.shouldLog(SessionLog.FINE)) {
                log.log(SessionLog.FINE, "EclipseLink is using " + validationImplJar + " as BeanValidation implementation.");
            }
        }
    }

    /**
     * INTERNAL:
     * Retrieves code source of validator.
     *
     * @return Validator code source. May be null.
     */
    private CodeSource getValidatorCodeSource() {
        return PrivilegedAccessHelper.callDoPrivileged(
                () -> validator.getClass().getProtectionDomain().getCodeSource()
        );
    }

    /**
     * INTERNAL:
     *
     * Value Object class that provides adequate toString() method which describes
     * on which field a Validation Constraint was violated and includes it's violationDescription.
     */
    private static class ConstraintViolationInfo {
        /**
         * Description of constraint violation.
         */
        private final String violationDescription;

        /**
         * Path to element on which the constraint violation occurred.
         */
        private final Path propertyPath;

        /**
         * Private constructor. Only to be used from within {@link org.eclipse.persistence.jaxb.JAXBBeanValidator}.
         *
         * @param message description of constraint violation
         * @param propertyPath path to element on which the constraint violation occurred
         */
        private ConstraintViolationInfo(String message, Path propertyPath){
            this.violationDescription = message;
            this.propertyPath = propertyPath;
        }

        @Override
        public String toString() {
            return "Violated constraint on property " + propertyPath + ": \"" + violationDescription + "\".";
        }
    }
}
