/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 1998, 2018 IBM Corporation. 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:
//     tware, ssmith = 1.0 - Generic JPA deployment (OSGI, EE, SE)
//     11/04/2014 - Rick Curtis
//       - 450010 : Add java se test bucket
//     08/29/2016 Jody Grassel
//       - 500441: Eclipselink core has System.getProperty() calls that are not potentially executed under doPriv()
package org.eclipse.persistence.internal.jpa.deployment;

import java.io.FileWriter;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import jakarta.persistence.spi.ClassTransformer;
import jakarta.persistence.spi.PersistenceUnitInfo;

import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider;
import org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.jpa.Archive;
import org.eclipse.persistence.jpa.PersistenceProvider;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;

/**
 * Base class for all JPA initialization classes.  This is an abstract class that provides the framework
 * for JPA initialization (finding and initializing persistence units).  Subclasses implement the abstract methods
 * to provide customized functionality
 *
 * @see JavaSECMPInitializer
 * @author tware
 *
 */
public abstract class JPAInitializer {

    // The internal loader is used by applications that do weaving to pre load classes
    // When this flag is set to false, we will not be able to weave.
    protected boolean shouldCreateInternalLoader = true;

    protected ClassLoader initializationClassloader = null;

    // Cache the initial puInfos - those used by  initialEmSetupImpls
    protected Map<String, SEPersistenceUnitInfo> initialPuInfos;
    // Cache the initial emSetupImpls - those created and predeployed by JavaSECMPInitializer.initialize method.
    protected Map<String, EntityManagerSetupImpl> initialEmSetupImpls;

    // Initializers keyed by their initializationClassloaders
    protected static Map<ClassLoader, JPAInitializer> initializers = new Hashtable<>();

    protected JPAInitializer() {
    }

    /**
     * Initialize the logging file if it is specified by the system property.
     */
    public static void initializeTopLinkLoggingFile() {
        String loggingFile = PrivilegedAccessHelper.getSystemProperty(PersistenceUnitProperties.LOGGING_FILE);
        try {
            if (loggingFile != null) {
                AbstractSessionLog.getLog().setWriter(new FileWriter(loggingFile));
            }
        } catch (IOException e) {
            AbstractSessionLog.getLog().log(SessionLog.WARNING, "cmp_init_default_logging_file_is_invalid",loggingFile,e);
        }
    }

    /**
     * predeploy (with deploy) is one of the two steps required in deployment of entities
     * This method will prepare to call predeploy, call it and finally register the
     * transformer returned to be used for weaving.
     */
    public EntityManagerSetupImpl callPredeploy(SEPersistenceUnitInfo persistenceUnitInfo, Map m, String persistenceUnitUniqueName, String sessionName) {
        AbstractSessionLog.getLog().log(SessionLog.FINER, SessionLog.JPA, "cmp_init_invoke_predeploy", persistenceUnitInfo.getPersistenceUnitName());
        Map mergedProperties = EntityManagerFactoryProvider.mergeMaps(m, persistenceUnitInfo.getProperties());
        // Bug#4452468  When globalInstrumentation is null, there is no weaving
        checkWeaving(mergedProperties);

        Set<String> tempLoaderSet = PersistenceUnitProcessor.buildClassSet(persistenceUnitInfo, m);
        // Create the temp loader that will not cache classes for entities in our persistence unit
        ClassLoader tempLoader = createTempLoader(tempLoaderSet);
        persistenceUnitInfo.setNewTempClassLoader(tempLoader);

        EntityManagerSetupImpl emSetupImpl = new EntityManagerSetupImpl(persistenceUnitUniqueName, sessionName);

        // A call to predeploy will partially build the session we will use
        final ClassTransformer transformer = emSetupImpl.predeploy(persistenceUnitInfo, mergedProperties);

        // After preDeploy it's impossible to weave again - so may substitute the temporary classloader with the real one.
        // The temporary classloader could be garbage collected even if the puInfo is cached for the future use by other emSetupImpls.
        persistenceUnitInfo.setNewTempClassLoader(persistenceUnitInfo.getClassLoader());

        registerTransformer(transformer, persistenceUnitInfo, m);
        return emSetupImpl;
    }

    /**
     * Check whether weaving is possible and update the properties and variable as appropriate
     * @param properties The list of properties to check for weaving and update if weaving is not needed
     */
    public abstract void checkWeaving(Map properties);

    /**
     * Create a temporary class loader that can be used to inspect classes and then
     * thrown away.  This allows classes to be introspected prior to loading them
     * with application's main class loader enabling weaving.
     */
    protected abstract ClassLoader createTempLoader(Collection col);

    protected abstract ClassLoader createTempLoader(Collection col, boolean shouldOverrideLoadClassForCollectionMembers);

    /**
     * Find PersistenceUnitInfo corresponding to the persistence unit name.
     * Returns null if either persistence unit either not found or provider is not supported.
     */
    public SEPersistenceUnitInfo findPersistenceUnitInfo(String puName, Map m) {
        SEPersistenceUnitInfo persistenceUnitInfo = null;
        if(initialPuInfos != null) {
            persistenceUnitInfo = initialPuInfos.get(puName);
        }
        if(persistenceUnitInfo != null) {
            return persistenceUnitInfo;
        }
        persistenceUnitInfo = (SEPersistenceUnitInfo) m.get(PersistenceUnitProperties.ECLIPSELINK_SE_PUINFO);
        if (persistenceUnitInfo != null) {
            return persistenceUnitInfo;
        }
        return findPersistenceUnitInfoInArchives(puName, m);
    }

    /**
     * Find PersistenceUnitInfo corresponding to the persistence unit name.
     * Returns null if either persistence unit either not found or provider is not supported.
     */
    protected SEPersistenceUnitInfo findPersistenceUnitInfoInArchives(String puName, Map m) {
        SEPersistenceUnitInfo persistenceUnitInfo = null;
        // mkeith - get resource name from prop and include in subsequent call
        String descriptorPath = (String) m.get(PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML);
        final Set<Archive> pars;
        if (descriptorPath != null) {
            pars = PersistenceUnitProcessor.findPersistenceArchives(initializationClassloader, descriptorPath);
        } else {
            pars = PersistenceUnitProcessor.findPersistenceArchives(initializationClassloader);
        }
        try {
            for (Archive archive: pars) {
                persistenceUnitInfo = findPersistenceUnitInfoInArchive(puName, archive, m);
                if(persistenceUnitInfo != null) {
                    break;
                }
            }
        } finally {
            for (Archive archive: pars) {
                archive.close();
            }
        }
        return persistenceUnitInfo;
    }

    /**
     * Find PersistenceUnitInfo corresponding to the persistence unit name in the archive.
     * Returns null if either persistence unit either not found or provider is not supported.
     */
    protected SEPersistenceUnitInfo findPersistenceUnitInfoInArchive(String puName, Archive archive, Map m){
        Iterator<SEPersistenceUnitInfo> persistenceUnits = PersistenceUnitProcessor.getPersistenceUnits(archive, initializationClassloader).iterator();
        while (persistenceUnits.hasNext()) {
            SEPersistenceUnitInfo persistenceUnitInfo = persistenceUnits.next();
            if(isPersistenceProviderSupported(persistenceUnitInfo.getPersistenceProviderClassName()) &&  persistenceUnitInfo.getPersistenceUnitName().equals(puName)) {
                return persistenceUnitInfo;
            }
        }
        return null;
    }

    /**
     * Returns whether the given persistence provider class is supported by this implementation
     * @param providerClassName
     * @return
     */
    public boolean isPersistenceProviderSupported(String providerClassName){
        return (providerClassName == null) || providerClassName.equals("") || providerClassName.equals(EntityManagerFactoryProvider.class.getName()) || providerClassName.equals(PersistenceProvider.class.getName());
    }

    /**
     * Create a list of java.lang.Class that contains the classes of all the entities
     * that we will be deploying.
     */
    protected Set loadEntityClasses(Collection entityNames, ClassLoader classLoader) {
        Set<Object> entityClasses = new HashSet<>();

        // Load the classes using the loader passed in
        AbstractSessionLog.getLog().log(SessionLog.FINER, SessionLog.JPA, "cmp_loading_entities_using_loader", classLoader);
        for (Iterator iter = entityNames.iterator(); iter.hasNext();) {
            String entityClassName = (String)iter.next();
            try {
                entityClasses.add(classLoader.loadClass(entityClassName));
            } catch (ClassNotFoundException cnfEx) {
                throw ValidationException.entityClassNotFound(entityClassName, classLoader, cnfEx);
            }
        }
        return entityClasses;
    }

    /**
     * Register a transformer.  This method should be overridden to provide the appropriate transformer
     * registration for the environment
     * @param transformer
     * @param persistenceUnitInfo
     */
    public abstract void registerTransformer(final ClassTransformer transformer, PersistenceUnitInfo persistenceUnitInfo, Map properties);

    /**
     * Indicates whether puName uniquely defines the persistence unit.
     */
    public boolean isPersistenceUnitUniquelyDefinedByName() {
        return true;
    }

    /**
     * In case persistence unit is not uniquely defined by name
     * this method is called to generate a unique name.
     */
    public String createUniquePersistenceUnitName(PersistenceUnitInfo puInfo) {
        return PersistenceUnitProcessor.buildPersistenceUnitName(puInfo.getPersistenceUnitRootUrl(), puInfo.getPersistenceUnitName());
    }

    public EntityManagerSetupImpl extractInitialEmSetupImpl(String puName) {
        if(this.initialEmSetupImpls != null) {
            return this.initialEmSetupImpls.remove(puName);
        } else {
            return null;
        }
    }

    /**
     * This method initializes the container.  Essentially, it will try to load the
     * class that contains the list of entities and reflectively call the method that
     * contains that list.  It will then initialize the container with that list.
     */
    public void initialize(Map m) {
        boolean keepInitialMaps = keepAllPredeployedPersistenceUnits();
        if(keepInitialMaps) {
            this.initialPuInfos = new HashMap<>();
        }
        // always create initialEmSetupImpls - it's used to check for puName uniqueness in initPersistenceUnits
        this.initialEmSetupImpls = new HashMap<>();
        // ailitchev - copied from findPersistenceUnitInfoInArchives: mkeith - get resource name from prop and include in subsequent call
        String descriptorPath = (String) m.get(PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML);
        final Set<Archive> pars;
        if (descriptorPath != null) {
            pars = PersistenceUnitProcessor.findPersistenceArchives(initializationClassloader, descriptorPath);
        } else {
            pars = PersistenceUnitProcessor.findPersistenceArchives(initializationClassloader);
        }
        try {
            for (Archive archive: pars) {
                AbstractSessionLog.getLog().log(SessionLog.FINER, SessionLog.JPA, "cmp_init_initialize", archive);
                initPersistenceUnits(archive, m);
            }
        } finally {
            for (Archive archive: pars) {
                archive.close();
            }
            this.initialEmSetupImpls = null;
        }
    }

    /**
     * Initialize all persistence units found on initializationClassLoader.
     * Initialization is a two phase process.  First the predeploy process builds the metadata
     * and creates any required transformers.
     * Second the deploy process creates an EclipseLink session based on that metadata.
     */
    protected void initPersistenceUnits(Archive archive, Map m){
        Iterator<SEPersistenceUnitInfo> persistenceUnits = PersistenceUnitProcessor.getPersistenceUnits(archive, initializationClassloader).iterator();
        while (persistenceUnits.hasNext()) {
            SEPersistenceUnitInfo persistenceUnitInfo = persistenceUnits.next();
            if(isPersistenceProviderSupported(persistenceUnitInfo.getPersistenceProviderClassName())) {
                // puName uniquely defines the pu on a class loader
                String puName = persistenceUnitInfo.getPersistenceUnitName();

                // don't add puInfo that could not be used standalone (only as composite member).
                if (EntityManagerSetupImpl.mustBeCompositeMember(persistenceUnitInfo)) {
                    continue;
                }

                // If puName is already in the map then there are two jars containing persistence units with the same name.
                // Because both are loaded from the same classloader there is no way to distinguish between them - throw exception.
                EntityManagerSetupImpl anotherEmSetupImpl = null;
                if (initialEmSetupImpls != null){
                    anotherEmSetupImpl = this.initialEmSetupImpls.get(puName);
                }
                if(anotherEmSetupImpl != null) {
                    EntityManagerSetupImpl.throwPersistenceUnitNameAlreadyInUseException(puName, persistenceUnitInfo, anotherEmSetupImpl.getPersistenceUnitInfo());
                }

                // Note that session name is extracted only from puInfo, the passed properties ignored.
                String sessionName = EntityManagerSetupImpl.getOrBuildSessionName(Collections.emptyMap(), persistenceUnitInfo, puName);
                EntityManagerSetupImpl emSetupImpl = callPredeploy(persistenceUnitInfo, m, puName, sessionName);
                if (initialEmSetupImpls != null){
                    this.initialEmSetupImpls.put(puName, emSetupImpl);
                }
                if (initialPuInfos != null){
                    this.initialPuInfos.put(puName, persistenceUnitInfo);
                }
            }
        }
    }

    /**
     * Indicates whether initialPuInfos and initialEmSetupImpls are used.
     */
    protected boolean keepAllPredeployedPersistenceUnits() {
        return false;
    }

    public ClassLoader getInitializationClassLoader() {
        return this.initializationClassloader;
    }
}
