/*
 * 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:
//     Oracle - initial API and implementation from Oracle TopLink
//     05/16/2008-1.0M8 Guy Pelletier
//       - 218084: Implement metadata merging functionality between mapping files
//     05/23/2008-1.0M8 Guy Pelletier
//       - 211330: Add attributes-complete support to the EclipseLink-ORM.XML Schema
//     12/10/2008-1.1 Michael O'Brien
//       - 257606: Add orm.xml schema validation true/(false) flag support in persistence.xml
//     01/28/2009-2.0 Guy Pelletier
//       - 248293: JPA 2.0 Element Collections (part 1)
//     03/27/2009-2.0 Guy Pelletier
//       - 241413: JPA 2.0 Add EclipseLink support for Map type attributes
//     03/08/2010-2.1 Guy Pelletier
//       - 303632: Add attribute-type for mapping attributes to EclipseLink-ORM
//     05/14/2010-2.1 Guy Pelletier
//       - 253083: Add support for dynamic persistence using ORM.xml/eclipselink-orm.xml
//     04/01/2011-2.3 Guy Pelletier
//       - 337323: Multi-tenant with shared schema support (part 2)
//     09/20/2011-2.3.1 Guy Pelletier
//       - 357476: Change caching default to ISOLATED for multitenant's using a shared EMF.
//     06/20/2012-2.5 Guy Pelletier
//       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
//     10/09/2012-2.5 Guy Pelletier
//       - 374688: JPA 2.1 Converter support
//     08/18/2014-2.5 Jody Grassel (IBM Corporation)
//       - 440802: xml-mapping-metadata-complete does not exclude @Entity annotated entities
//     11/23/2017: Scott Marlow
//       - 414974: allow eclipselink.archive.factory to be specified as an integration property of PersistenceProvider.createContainerEntityManagerFactory(PersistenceUnitInfo, Map)
package org.eclipse.persistence.internal.jpa.metadata;

import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import jakarta.persistence.spi.PersistenceUnitInfo;

import org.eclipse.persistence.config.DescriptorCustomizer;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.exceptions.PersistenceUnitLoadingException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl;
import org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor;
import org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor.Mode;
import org.eclipse.persistence.internal.jpa.metadata.accessors.classes.ClassAccessor;
import org.eclipse.persistence.internal.jpa.metadata.accessors.classes.ConverterAccessor;
import org.eclipse.persistence.internal.jpa.metadata.accessors.classes.EmbeddableAccessor;
import org.eclipse.persistence.internal.jpa.metadata.accessors.classes.EntityAccessor;
import org.eclipse.persistence.internal.jpa.metadata.accessors.classes.MappedSuperclassAccessor;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataAsmFactory;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataClass;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataFactory;
import org.eclipse.persistence.internal.jpa.metadata.converters.StructConverterMetadata;
import org.eclipse.persistence.internal.jpa.metadata.xml.XMLEntityMappings;
import org.eclipse.persistence.internal.jpa.metadata.xml.XMLEntityMappingsReader;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.jpa.Archive;
import org.eclipse.persistence.jpa.metadata.MetadataSource;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;

/**
 * INTERNAL:
 * The object/relational metadata processor for the EJB3.0 specification.
 *
 * @author Guy Pelletier
 * @since TopLink EJB 3.0 Reference Implementation
 */
public class MetadataProcessor {
    protected ClassLoader m_loader;
    protected MetadataFactory m_factory;
    protected MetadataProject m_project;
    protected AbstractSession m_session;
    protected Map<String, Object> m_predeployProperties;
    protected MetadataProcessor m_compositeProcessor;
    protected Set<MetadataProcessor> m_compositeMemberProcessors;
    protected MetadataSource m_metadataSource;

    /**
     * INTERNAL:
     * Empty processor to be used as a composite processor.
     */
    public MetadataProcessor() {}

    /**
     * INTERNAL:
     * Called from EntityManagerSetupImpl. The 'real' EJB 3.0 processing
     * that includes XML and annotations.
     */
    public MetadataProcessor(PersistenceUnitInfo puInfo, AbstractSession session, ClassLoader loader, boolean weaveLazy, boolean weaveEager, boolean weaveFetchGroups, boolean multitenantSharedEmf, boolean multitenantSharedCache, Map<String, Object> predeployProperties, MetadataProcessor compositeProcessor) {
        m_loader = loader;
        m_session = session;
        m_project = new MetadataProject(puInfo, session, weaveLazy, weaveEager, weaveFetchGroups, multitenantSharedEmf, multitenantSharedCache);
        m_predeployProperties = predeployProperties;
        m_compositeProcessor = compositeProcessor;
        if (m_compositeProcessor != null) {
            m_compositeProcessor.addCompositeMemberProcessor(this);
            m_project.setCompositeProcessor(m_compositeProcessor);
        }
    }

    /**
     * INTERNAL:
     * Add containedProcessor to compositeProcessor.
     */
    public void addCompositeMemberProcessor(MetadataProcessor compositeMemberProcessor) {
        if (m_compositeMemberProcessors == null) {
            m_compositeMemberProcessors = new HashSet<>();
        }
        m_compositeMemberProcessors.add(compositeMemberProcessor);
    }

    /**
     * INTERNAL:
     * Method to place EntityListener's on the descriptors from the given
     * session. This call is made from the EntityManagerSetup deploy call.
     */
    public void addEntityListeners() {
        // Process the listeners for all the class accessors, but before
        // doing so, update the accessors associated class since the loader
        // should have changed changed.
        for (EntityAccessor accessor : m_project.getEntityAccessors()) {
            accessor.setJavaClass(accessor.getDescriptor().getJavaClass());
            accessor.processListeners(m_loader);
        }
    }

    /**
     * INTERNAL:
     * Method to place NamedQueries and NamedNativeQueries on the given session.
     * This call is made from the EntityManagerSetup deploy call.
     */
    public void addNamedQueries() {
        m_project.processQueries();
    }

    /**
     * INTERNAL:
     * During EntityManagerSetup deploy, using the real class loader we must
     * create our dynamic classes.
     */
    public void createDynamicClasses() {
        m_project.createDynamicClasses(m_loader);
    }

    /**
     * INTERNAL:
     * Return compositeProcessor.
     */
    public MetadataProcessor getCompositeProcessor() {
        return m_compositeProcessor;
    }

    /**
     * INTERNAL:
     */
    public MetadataFactory getMetadataFactory() {
        return m_factory;
    }

    /**
     * INTERNAL:
     */
    public MetadataSource getMetadataSource(){
        return m_metadataSource;
    }

    /**
     * INTERNAL:
     * Returns projects owned by compositeProcessor minus the passed project.
     */
    public Set<MetadataProject> getPearProjects(MetadataProject project) {
        Set<MetadataProject> pearProjects = new HashSet<>();
        if (m_compositeMemberProcessors != null) {
            for(MetadataProcessor processor : m_compositeMemberProcessors) {
                MetadataProject pearProject = processor.getProject();
                if(pearProject != project) {
                    pearProjects.add(pearProject);
                }
            }
        }
        return pearProjects;
    }

    /**
     * INTERNAL:
     * Return a set of class names for each entity, embeddable and mapped
     * superclass found in the mapping files to be processed by the
     * MetadataProcessor.
     */
    public Set<String> getPersistenceUnitClassSetFromMappingFiles() {
        HashSet<String> classSet = new HashSet<String>();

        for (XMLEntityMappings entityMappings : m_project.getEntityMappings()) {
            for (ClassAccessor entity : entityMappings.getEntities()) {
                classSet.add(entityMappings.getPackageQualifiedClassName(entity.getClassName()));
            }

            for (ClassAccessor embeddable : entityMappings.getEmbeddables()) {
                classSet.add(entityMappings.getPackageQualifiedClassName(embeddable.getClassName()));
            }

            for (ClassAccessor mappedSuperclass : entityMappings.getMappedSuperclasses()) {
                classSet.add(entityMappings.getPackageQualifiedClassName(mappedSuperclass.getClassName()));
            }
        }

        return classSet;
    }

    /**
     * INTERNAL:
     */
    public MetadataProject getProject() {
        return m_project;
    }

    /**
     * INTERNAL:
     * Adds a list of StructConverter string names that were defined in the
     * metadata of this project to the native EclipseLink project.
     *
     * These StructConverters can be added to the Project to be processed later
     */
    public void addStructConverterNames() {
        List<String> structConverters = new ArrayList<String>();
        for (StructConverterMetadata converter: m_project.getStructConverters()) {
            structConverters.add(converter.getConverterClassName());
        }
        if (!structConverters.isEmpty()) {
            m_session.getProject().setStructConverters(structConverters);
        }
    }

    /**
     * INTERNAL:
     * Handle an exception that occurred while processing ORM xml.
     */
    protected void handleORMException(RuntimeException e, String mappingFile, boolean throwException){
        if (m_session == null) {
            // Metadata processor is mainly used with a session. Java SE
            // bootstrapping uses some functions such as ORM processing without
            // a session. In these cases, it is impossible to get the session
            // to properly handle the exception. As a result we log an error.
            // The same code will be called later in the bootstrapping code
            // and the error will be handled then.
            AbstractSessionLog.getLog().log(SessionLog.WARNING, SessionLog.METADATA, EntityManagerSetupImpl.ERROR_LOADING_XML_FILE, new Object[] {mappingFile, e});
        } else if (!throwException) {
            // fail quietly
            m_session.log(SessionLog.WARNING, SessionLog.METADATA, EntityManagerSetupImpl.ERROR_LOADING_XML_FILE, new Object[] {mappingFile, e});
        } else {
            // fail loudly
            m_session.handleException(e);
        }
    }

    /**
     * INTERNAL:
     * This method is responsible for discovering all the entity classes for
     * this PU and adding corresponding MetadataDescriptor in the
     * MetadataProject.
     *
     * This method will also gather all the weavable classes for this PU.
     * Currently, entity and embeddable classes are weavable.
     *
     * NOTE: The order of processing should not be changed as the steps are
     * dependent on one another.
     */
    protected void initPersistenceUnitClasses() {
        // 1 - Iterate through the classes that are defined in the <mapping>
        // files and add them to the map. This will merge the accessors where
        // necessary.
        HashMap<String, EntityAccessor> entities = new HashMap<String, EntityAccessor>();
        HashMap<String, EmbeddableAccessor> embeddables = new HashMap<String, EmbeddableAccessor>();

        for (XMLEntityMappings entityMappings : m_project.getEntityMappings()) {
            entityMappings.initPersistenceUnitClasses(entities, embeddables);
        }

        // 2 - Iterate through all the XML entities and add them to the project
        // and apply any persistence unit defaults.
        for (EntityAccessor entity : entities.values()) {
            // This will apply global persistence unit defaults.
            m_project.addEntityAccessor(entity);

            // This will override any global settings.
            entity.getEntityMappings().processEntityMappingsDefaults(entity);
        }

        // 3 - Iterate though all the XML embeddables and add them to the
        // project and apply any persistence unit defaults.
        for (EmbeddableAccessor embeddable : embeddables.values()) {
            // This will apply global persistence unit defaults.
            m_project.addEmbeddableAccessor(embeddable);

            // This will override any global settings.
            embeddable.getEntityMappings().processEntityMappingsDefaults(embeddable);
        }

        // Check if the xml-mapping-metadata-complete was declared.  If so, then ignore <class> entries defined
        // in the persistence unit, as by definition only elements declared in ORM XML are to be permitted.
        if (m_project.getPersistenceUnitMetadata() != null && m_project.getPersistenceUnitMetadata().isXMLMappingMetadataComplete()) {
            return;
        }

        // 4 - Iterate through the classes that are referenced from the
        // persistence.xml file.
        PersistenceUnitInfo persistenceUnitInfo = m_project.getPersistenceUnitInfo();
        List<String> classNames = new ArrayList<String>();

        // Add all the <class> specifications.
        classNames.addAll(persistenceUnitInfo.getManagedClassNames());

        // Add all the classes from the <jar> specifications.
        for (URL url : persistenceUnitInfo.getJarFileUrls()) {
            classNames.addAll(PersistenceUnitProcessor.getClassNamesFromURL(url, m_loader, null));
        }

        // Add all the classes off the classpath at the persistence unit root url.
        Set<String> unlistedClasses = Collections.emptySet();
        if (! persistenceUnitInfo.excludeUnlistedClasses()) {
            unlistedClasses = PersistenceUnitProcessor.getClassNamesFromURL(persistenceUnitInfo.getPersistenceUnitRootUrl(), m_loader, m_predeployProperties);
        }

        // 5 - Go through all the class names we found and add those classes
        // that have not yet been added. Be sure to check that the accessor
        // does not already exist since adding an accessor will merge its
        // contents with an existing accessor and we only want that to happen
        // in the XML case. Also, don't add an entity accessor if an embeddable
        // accessor to the same class exists (and vice versa). XML accessors
        // are loaded first, so preserve what we find there.
        Iterator<String> iterator = classNames.iterator();
        boolean unlisted = false;
        while (iterator.hasNext() || !unlisted) {
            if (!iterator.hasNext() && !unlisted) {
                iterator = unlistedClasses.iterator();
                unlisted = true;
            }
            if (iterator.hasNext()) {
                String className = iterator.next();
                MetadataClass candidateClass = m_factory.getMetadataClass(className, unlisted);
                // JBoss Bug 227630: Do not process a null class whether it was from a
                // NPE or a CNF, a warning or exception is thrown in loadClass()
                if (candidateClass != null) {
                    if (PersistenceUnitProcessor.isEntity(candidateClass) && ! m_project.hasEntity(candidateClass) && ! m_project.hasEmbeddable(candidateClass)) {
                        m_project.addEntityAccessor(new EntityAccessor(PersistenceUnitProcessor.getEntityAnnotation(candidateClass), candidateClass, m_project));
                    } else if (PersistenceUnitProcessor.isEmbeddable(candidateClass) && ! m_project.hasEmbeddable(candidateClass) && ! m_project.hasEntity(candidateClass)) {
                        m_project.addEmbeddableAccessor(new EmbeddableAccessor(PersistenceUnitProcessor.getEmbeddableAnnotation(candidateClass), candidateClass, m_project));
                    } else if (PersistenceUnitProcessor.isStaticMetamodelClass(candidateClass)) {
                        m_project.addStaticMetamodelClass(PersistenceUnitProcessor.getStaticMetamodelAnnotation(candidateClass), candidateClass);
                    } else if (PersistenceUnitProcessor.isConverter(candidateClass) && ! m_project.hasConverterAccessor(candidateClass)) {
                        m_project.addConverterAccessor(new ConverterAccessor(PersistenceUnitProcessor.getConverterAnnotation(candidateClass), candidateClass, m_project));
                    } else if (PersistenceUnitProcessor.isMappedSuperclass(candidateClass) && ! m_project.hasMappedSuperclass(candidateClass)) {
                        // ensure mapped superclasses will be added to the metamodel even if they do not have entity subclasses
                        // add the mapped superclass to keep track of it in case it is not processed later (has no subclasses).
                        m_project.addMappedSuperclass(new MappedSuperclassAccessor(
                                PersistenceUnitProcessor.getMappedSuperclassAnnotation(candidateClass),
                                candidateClass, m_project));
                    }
                }
            }
        }
    }

    /**
     * INTERNAL:
     * This method is responsible for figuring out list of mapping files to
     * read into XMLEntityMappings objects and store on the project. Note,
     * the order the files are discovered and read is very important so do
     * not change the order of invocation.
     */
    public void loadMappingFiles(boolean throwExceptionOnFail) {
        // Read all the standard XML mapping files first.
        loadStandardMappingFiles(MetadataHelper.JPA_ORM_FILE);

        // Read all the explicitly specified mapping files second.
        loadSpecifiedMappingFiles(throwExceptionOnFail);

        // Read all the standard eclipselink files last (if the user hasn't
        // explicitly excluded them). The eclipselink orm files will be
        // processed last therefore allowing them to override and merge
        // metadata where necessary. Note: we want the eclipselink orm
        // metadata to merge into standard jpa files and not vice versa.
        // Loading them last will ensure this happens.
        Boolean excludeEclipseLinkORM = Boolean.valueOf((String) m_project.getPersistenceUnitInfo().getProperties().get(PersistenceUnitProperties.EXCLUDE_ECLIPSELINK_ORM_FILE));
        if (! excludeEclipseLinkORM) {
            loadStandardMappingFiles(MetadataHelper.ECLIPSELINK_ORM_FILE);
        }

        if (m_metadataSource !=null) {
            XMLEntityMappings entityMappings = m_metadataSource.getEntityMappings(this.m_predeployProperties, m_loader, m_session.getSessionLog());
            if (entityMappings != null) {
                m_project.addEntityMappings(entityMappings);
            }
        }
    }

    /**
     * INTERNAL:
     */
    protected void loadSpecifiedMappingFiles(boolean throwExceptionOnFail) {
        PersistenceUnitInfo puInfo = m_project.getPersistenceUnitInfo();

        for (String mappingFileName : puInfo.getMappingFileNames()) {
            try {
                Enumeration<URL> mappingFileURLs = m_loader.getResources(mappingFileName);

                if (!mappingFileURLs.hasMoreElements()){
                    mappingFileURLs = m_loader.getResources("/./" + mappingFileName);
                }

                if (mappingFileURLs.hasMoreElements()) {
                    URL nextURL = mappingFileURLs.nextElement();
                    if (nextURL == null) {
                        nextURL = mappingFileURLs.nextElement();
                    }

                    if (mappingFileURLs.hasMoreElements()) {
                        // Switched to warning, same file can be on the classpath twice in some deployments,
                        // should not be an error.
                        Throwable throwable = ValidationException.nonUniqueMappingFileName(puInfo.getPersistenceUnitName(), mappingFileName);
                        getSessionLog().logThrowable(SessionLog.FINER, SessionLog.METADATA, throwable);
                    }

                    // Read the document through OX and add it to the project.
                    m_project.addEntityMappings(XMLEntityMappingsReader.read(nextURL, m_loader, m_project.getPersistenceUnitInfo().getProperties()));
                } else {
                    handleORMException(ValidationException.mappingFileNotFound(puInfo.getPersistenceUnitName(), mappingFileName), mappingFileName, throwExceptionOnFail);
                }
            } catch (IOException e) {
                handleORMException(PersistenceUnitLoadingException.exceptionLoadingORMXML(mappingFileName, e), mappingFileName, throwExceptionOnFail);
            }
        }
    }

    /**
     * INTERNAL:
     */
    protected void loadStandardMappingFiles(String ormXMLFile) {
        PersistenceUnitInfo puInfo = m_project.getPersistenceUnitInfo();
        Collection<URL> rootUrls = new HashSet<URL>(puInfo.getJarFileUrls());
        rootUrls.add(puInfo.getPersistenceUnitRootUrl());

        for (URL rootURL : rootUrls) {
            getSessionLog().log(SessionLog.FINER, SessionLog.METADATA, "searching_for_default_mapping_file", new Object[] { ormXMLFile, rootURL }, true);
            URL ormURL = null;

            Archive par = null;
            try {
                par = PersistenceUnitProcessor.getArchiveFactory(m_loader, m_predeployProperties).createArchive(rootURL, null);

                if (par != null) {
                    ormURL = par.getEntryAsURL(ormXMLFile);

                    if (ormURL != null) {
                        getSessionLog().log(SessionLog.FINER, SessionLog.METADATA, "found_default_mapping_file", new Object[] { ormURL, rootURL }, true);

                        // Read the document through OX and add it to the project., pass persistence unit properties for any orm properties set there
                        XMLEntityMappings entityMappings = XMLEntityMappingsReader.read(ormURL, m_loader, m_project.getPersistenceUnitInfo().getProperties());
                        entityMappings.setIsEclipseLinkORMFile(ormXMLFile.equals(MetadataHelper.ECLIPSELINK_ORM_FILE));
                        m_project.addEntityMappings(entityMappings);
                    }
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            } catch (URISyntaxException e) {
                throw new RuntimeException(e);
            } finally {
                if (par != null) {
                    par.close();
                }
            }
        }
    }

    /**
     * INTERNAL:
     * Return the SessionLog from the Session. If the session is null,
     * return the AbstractSessionLog's SessionLog.
     * @return SessionLog
     */
    protected SessionLog getSessionLog() {
        if (m_session != null) {
            return m_session.getSessionLog();
        } else {
            return AbstractSessionLog.getLog();
        }
    }

    /**
     * INTERNAL:
     * Process the customizer for those entities and embeddables that have one
     * defined. This must be the last thing called on this processor before
     * cleanup.
     */
    public void processCustomizers() {
        for (ClassAccessor classAccessor: m_project.getAccessorsWithCustomizer()) {
            DescriptorCustomizer customizer = (DescriptorCustomizer) MetadataHelper.getClassInstance(classAccessor.getCustomizerClass().getName(), m_loader);

            try {
                customizer.customize(classAccessor.getDescriptor().getClassDescriptor());
            } catch (Exception e) {
                getSessionLog().logThrowable(SessionLog.FINER, SessionLog.METADATA, e);
            }
        }
    }

    /**
     * INTERNAL:
     * Performs the initialization of the persistence unit classes and then
     * processes the xml metadata.
     * Note: Do not change the order of invocation of various methods.
     */
    public void processEntityMappings(PersistenceUnitProcessor.Mode mode) {
        if (mode == PersistenceUnitProcessor.Mode.ALL || mode == PersistenceUnitProcessor.Mode.COMPOSITE_MEMBER_INITIAL) {
            m_factory = new MetadataAsmFactory(m_project.getLogger(), m_loader);

            // 1 - Process persistence unit meta data/defaults defined in ORM XML
            // instance documents in the persistence unit. If multiple conflicting
            // persistence unit meta data is found, this call will throw an
            // exception. The meta data we find here will be applied in the
            // initialize call below.
            for (XMLEntityMappings entityMappings : m_project.getEntityMappings()) {
                // Since this our first iteration through the entity mappings list,
                // set the project and loader references. This is very important
                // and must be done first!
                entityMappings.setLoader(m_loader);
                entityMappings.setProject(m_project);
                entityMappings.setMetadataFactory(m_factory);

                // Process the persistence unit metadata if defined.
                entityMappings.processPersistenceUnitMetadata();
            }

            // 2 - Initialize all the persistence unit class with the meta data we
            // processed in step 1.
            initPersistenceUnitClasses();

            // 3 - Now process the entity mappings metadata.
            for (XMLEntityMappings entityMappings : m_project.getEntityMappings()) {
                entityMappings.process();
            }
        }
    }

    /**
     * INTERNAL:
     * Process the ORM metadata on this processors metadata project
     * (representing a single persistence-unit)
     */
    public void processORMMetadata(PersistenceUnitProcessor.Mode mode) {
        if (mode == Mode.ALL || mode == Mode.COMPOSITE_MEMBER_INITIAL) {
            m_project.processStage1();
            m_project.processStage2();
        }

        if (mode != PersistenceUnitProcessor.Mode.COMPOSITE_MEMBER_INITIAL) {
            m_project.processStage3(mode);
        }
    }

    /**
     * INTERNAL:
     * Use this method to set the correct class loader that should be used
     * during processing. Currently, the class loader should only change
     * once, from preDeploy to deploy.
     */
    public void setClassLoader(ClassLoader loader) {
        m_loader = loader;
        m_factory.setLoader(loader);
        // Update the loader on all the entity mappings for this project.
        for (XMLEntityMappings entityMappings : m_project.getEntityMappings()) {
            entityMappings.setLoader(m_loader);
        }
    }

    /**
     * INTERNAL:
     * Use this method to set the MetadataSource class to use for loading
     * extensible mappings
     */
    public void setMetadataSource(MetadataSource source){
        m_metadataSource = source;
    }
}
