/*
 * 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
//     10/09/2012-2.5 Guy Pelletier
//       - 374688: JPA 2.1 Converter support
//     07/08/2014-2.5 Jody Grassel (IBM Corporation)
//       - 439163: JSE Bootstrapping does not handle "wsjar" URLs referencing war-contained resources
//     08/29/2016 Jody Grassel
//       - 500441: Eclipselink core has System.getProperty() calls that are not potentially executed under doPriv()
//     11/23/2017: Scott Marlow
//       - 414974: allow eclipselink.archive.factory to be specified as an integration property of PersistenceProvider.createContainerEntityManagerFactory(PersistenceUnitInfo, Map)
//     09/07/2018-3.0 Dmitry Polienko
//       - 326728: Fix persistence root calculation for WAR files
package org.eclipse.persistence.internal.jpa.deployment;

import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_CONVERTER;
import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_EMBEDDABLE;
import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_ENTITY;
import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_MAPPED_SUPERCLASS;
import static org.eclipse.persistence.internal.jpa.metadata.MetadataConstants.JPA_STATIC_METAMODEL;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

import jakarta.persistence.spi.PersistenceUnitInfo;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.config.SystemProperties;
import org.eclipse.persistence.exceptions.PersistenceUnitLoadingException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.exceptions.XMLParseException;
import org.eclipse.persistence.internal.helper.XMLHelper;
import org.eclipse.persistence.internal.jpa.deployment.xml.parser.PersistenceContentHandler;
import org.eclipse.persistence.internal.jpa.deployment.xml.parser.XMLException;
import org.eclipse.persistence.internal.jpa.deployment.xml.parser.XMLExceptionHandler;
import org.eclipse.persistence.internal.jpa.metadata.MetadataProcessor;
import org.eclipse.persistence.internal.jpa.metadata.MetadataProject;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataAnnotation;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataClass;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedGetSystemProperty;
import org.eclipse.persistence.internal.security.PrivilegedNewInstanceFromClass;
import org.eclipse.persistence.jpa.Archive;
import org.eclipse.persistence.jpa.ArchiveFactory;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

/**
 * INTERNAL:
 * Utility Class that deals with persistence archives for EJB 3.0
 * Provides functions like searching for persistence archives, processing
 * persistence.xml and searching for Entities in a Persistence archive
 */
public class PersistenceUnitProcessor {
    /**
     * Passed to processORMetadata method to indicate processing mode.
     * ALL used when independent persistence unit is created.
     * COMPOSITE_MEMBER_INITIAL, COMPOSITE_MEMBER_MIDDLE and COMPOSITE_MEMBER_FINAL used for a composite member persistence unit.
     */
    public enum Mode {
        ALL,
        COMPOSITE_MEMBER_INITIAL,
        COMPOSITE_MEMBER_MIDDLE,
        COMPOSITE_MEMBER_FINAL
    }

    /**
     * Cache the ArchiveFactory used to derive Archives.  This allows applications
     * to set the ArchiveFactory
     */
    public static ArchiveFactory ARCHIVE_FACTORY = null;

    /** Path to application classes directory in WAR file. */
    private static final String WEBINF_CLASSES_STR = "WEB-INF/classes/";

    /** Length of application classes directory path String. */
    private static final int WEBINF_CLASSES_LEN = WEBINF_CLASSES_STR.length();

    /**
     * Default constructor.
     */
    protected PersistenceUnitProcessor() {
    }

    /**
     * Entries in a zip file are directory entries using slashes to separate
     * them. Build a class name using '.' instead of slash and removing the
     * '.class' extension.
     */
    public static String buildClassNameFromEntryString(String classEntryString){
        String classNameForLoader = classEntryString;
        if (classEntryString.endsWith(".class")){
            classNameForLoader = classNameForLoader.substring(0, classNameForLoader.length() - 6);
            classNameForLoader = classNameForLoader.replace("/", ".");
        }
        return classNameForLoader;
    }

    /**
     * Build a set that contains all the class names at a URL.
     * @return a Set of class name strings
     */
    public static Set<String> buildClassSet(PersistenceUnitInfo persistenceUnitInfo, Map properties){
        Set<String> set = new HashSet<String>();
        set.addAll(persistenceUnitInfo.getManagedClassNames());
        ClassLoader loader = persistenceUnitInfo.getClassLoader();
        Iterator<URL> i = persistenceUnitInfo.getJarFileUrls().iterator();
        while (i.hasNext()) {
            set.addAll(getClassNamesFromURL(i.next(), loader, properties));
        }
        if (!persistenceUnitInfo.excludeUnlistedClasses()){
            set.addAll(getClassNamesFromURL(persistenceUnitInfo.getPersistenceUnitRootUrl(), loader, properties));
        }
        // No longer need to add classes from XML, as temp class loader is only used for sessions.xml.
        return set;
    }

    /**
     * Create a list of the entities that will be deployed. This list is built
     * from the information provided in the PersistenceUnitInfo argument.
     * The list contains Classes specified in the PersistenceUnitInfo's class
     * list and also files that are annotated with @Entity and @Embeddable in
     * the jar files provided in the persistence info. This list of classes will
     * used to build a deployment project and to decide what classes
     * to weave.
     */
    public static Collection<MetadataClass> buildEntityList(MetadataProcessor processor, ClassLoader loader) {
        ArrayList<MetadataClass> entityList = new ArrayList<MetadataClass>();
        for (String className : processor.getProject().getWeavableClassNames()) {
            entityList.add(processor.getMetadataFactory().getMetadataClass(className));
        }
        return entityList;
    }

    /**
     * Determine the URL path to the persistence unit
     * @param pxmlURL - URL of a resource belonging to the PU (obtained for
     * {@code descriptorLocation} via {@code Classloader.getResource(String)}).
     * @param descriptorLocation - the name of the resource.
     * @return The URL of the PU root containing the resource.
     * @throws IOException
     * @throws ValidationException if the resolved root doesn't conform to the
     * JPA specification (8.2)
     */
    public static URL computePURootURL(URL pxmlURL, String descriptorLocation) throws IOException, URISyntaxException {
        StringTokenizer tokenizer = new StringTokenizer(descriptorLocation, "/\\");
        int descriptorDepth = tokenizer.countTokens() - 1;
        URL result;
        String protocol = pxmlURL.getProtocol();
        if("file".equals(protocol)) { // NOI18N
            StringBuffer path = new StringBuffer();
            boolean firstElement = true;
            for (int i=0;i<descriptorDepth;i++){
                if (!firstElement){
                    path.append("/"); // 315097 URL use standard separators
                }
                path.append("..");
                firstElement = false;
            }
            // e.g. file:/tmp/META-INF/persistence.xml
            // 210280: any file url will be assumed to always reference a file (not a directory)
            result = new URL(pxmlURL, path.toString()); // NOI18N
        } else if("zip".equals(protocol) ||
                  "jar".equals(protocol) ||
                  "wsjar".equals(protocol)) {
            // e.g. file:/foo/bar.jar!/META-INF/persistence.xml
            // "zip:" URLs require additional handling.
            String spec = "zip".equals(protocol)
                ? "file:" + pxmlURL.getFile()
                : pxmlURL.getFile();

            // Warning: if we ever support nested archive URLs here, make sure
            // that we get the entry in the *innermost* archive.
            int separator = spec.lastIndexOf("!/");

            // It could be possible for a "zip:" or "wsjar:" URL to not have
            // an entry! In that case we take the root of the archive.
            String file = separator == -1 ? spec : spec.substring(0, separator);
            String entry = separator == -1 ? "" : spec.substring(separator + 2);

            // The jar file or directory whose META-INF directory contains
            // the persistence.xml file is termed the root of the persistence
            // unit. (JPA Spec, 8.2)
            if (!entry.endsWith(descriptorLocation)) {
                // Shouldn't happen unless we have a particularly tricky
                // classloader - which we're not obligated to support.
                throw ValidationException.invalidPersistenceRootUrl(pxmlURL, descriptorLocation);
            }

            String rootEntry = entry.substring(0, entry.length() - descriptorLocation.length());

            // "wsjar:" URLs always have an entry for historical reasons.
            result = !rootEntry.isEmpty() || "wsjar".equals(protocol)
                ? new URL("jar:" + file + "!/" + rootEntry)
                : new URL(file);

            // Since EclipseLink is a reference implementation, let's validate
            // the produced root!
            if (!isValidRootInArchive(file, rootEntry)) {
                throw ValidationException.invalidPersistenceRootUrl(pxmlURL, descriptorLocation);
            }

        } else if ("bundleentry".equals(protocol)) {
            // mkeith - add bundle protocol cases
            result = new URL("bundleentry://" + pxmlURL.getAuthority());
        } else if ("bundleresource".equals(protocol)) {
            result = new URL("bundleresource://" + pxmlURL.getAuthority());
        } else {
            StringBuffer path = new StringBuffer();
            for (int i=0;i<descriptorDepth;i++){
                path.append("../"); // 315097 URL use standard separators
            }
            // some other protocol
            result = new URL(pxmlURL, path.toString()); // NOI18N
        }
        result = fixUNC(result);
        return result;
    }


    /**
     * This method fixes incorrect authority attribute
     * that is set by JDK when UNC is used in classpath.
     * See JDK bug #6585937 and GlassFish issue #3209 for more details.
     */
    private static URL fixUNC(URL url) throws URISyntaxException, MalformedURLException, UnsupportedEncodingException
    {
        String protocol = url.getProtocol();
        if (!"file".equalsIgnoreCase(protocol)) {
            return url;
        }
        String authority= url.getAuthority();
        String file = url.getFile();
        if (authority != null) {
            AbstractSessionLog.getLog().finer(
                    "fixUNC: before fixing: url = " + url + ", authority = " + authority + ", file = " + file);
            assert(url.getPort() == -1);

            // See GlassFish issue https://glassfish.dev.java.net/issues/show_bug.cgi?id=3209 and
            // JDK issue http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6585937
            // When there is UNC path in classpath, the classloader.getResource
            // returns a file: URL with an authority component in it.
            // The URL looks like this:
            // file://ahost/afile.
            // Interestingly, authority and file components for the above URL
            // are either "ahost" and "/afile" or "" and "//ahost/afile" depending on
            // how the URL is obtained. If classpath is set as a jar with UNC,
            // the former is true, if the classpath is set as a directory with UNC,
            // the latter is true.
            String prefix = "";
            if (authority.length() > 0) {
                prefix = "////";
            } else if (file.startsWith("//")) {
                prefix = "//";
            }
            file = prefix.concat(authority).concat(file);
            url = new URL(protocol, null, file);
            AbstractSessionLog.getLog().finer(
                    "fixUNC: after fixing: url = " + url + ", authority = " + url.getAuthority() + ", file = " + url.getFile());
        }
        return url;
    }

    /**
     * Search the classpath for persistence archives. A persistence archive is
     * defined as any part of the class path that contains a META-INF directory
     * with a persistence.xml file in it. Return a list of the URLs of those
     * files. Use the current thread's context classloader to get the classpath.
     * We assume it is a URL class loader.
     */
    public static Set<Archive> findPersistenceArchives(){
        ClassLoader threadLoader = Thread.currentThread().getContextClassLoader();
        return findPersistenceArchives(threadLoader);
    }

    /**
     * Search the classpath for persistence archives. A persistence archive is
     * defined as any part of the class path that contains a META-INF directory
     * with a persistence.xml file in it. Return a list of {@link Archive}
     * representing the root of those files. It is the caller's responsibility
     * to close all the archives.
     *
     * @param loader the class loader to get the class path from
     */
    public static Set<Archive> findPersistenceArchives(ClassLoader loader){
        // allow alternate persistence location to be specified via system property.  This will allow persistence units
        // with alternate persistence xml locations to be weaved
        String descriptorLocation = PrivilegedAccessHelper.getSystemProperty(PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML, PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML_DEFAULT);

        return findPersistenceArchives(loader, descriptorLocation);
    }

    /**
     * Return a list of Archives representing the root of the persistence descriptor.
     * It is the caller's responsibility to close all the archives.
     *
     * @param loader the class loader to get the class path from
     */
    public static Set<Archive> findPersistenceArchives(ClassLoader loader, String descriptorPath){
        Archive archive = null;

        Set<Archive> archives = new HashSet<Archive>();

        // See if we are talking about an embedded descriptor
        int splitPosition = descriptorPath.indexOf("!/");

        try {
            // If not embedded descriptor then just use the regular descriptor path
            if (splitPosition == -1) {
                Enumeration<URL> resources = loader.getResources(descriptorPath);
                while (resources.hasMoreElements()){

                    URL descUrl = resources.nextElement();
                    if (descUrl == null) continue;

                    URL puRootUrl = computePURootURL(descUrl, descriptorPath);

                    archive = PersistenceUnitProcessor.getArchiveFactory(loader).createArchive(puRootUrl, descriptorPath, null);
                    if (archive == null) continue;

                    // archive = new BundleArchive(puRootUrl, descUrl);
                    archives.add(archive);
                }
            } else {
                // It is an embedded archive, so split up the parts
                String jarPrefixPath = descriptorPath.substring(0, splitPosition);
                String descPath = descriptorPath.substring(splitPosition+2);
                // TODO This causes the bundle to be resolved (not what we want)!
                URL prefixUrl = loader.getResource(jarPrefixPath);
                archive = PersistenceUnitProcessor.getArchiveFactory(loader).createArchive(prefixUrl, descPath, null);

                if (archive != null){
                    archives.add(archive);
                }
            }
        } catch (Exception ex){
            //clean up first
            for (Archive a : archives){
                a.close();
            }
            throw PersistenceUnitLoadingException.exceptionSearchingForPersistenceResources(loader, ex);
        }
        return archives;
    }

    /**
     * Return a list of Archives representing the root of the persistence descriptor.
     * It is the caller's responsibility to close all the archives.
     *
     * @param loader the class loader to get the class path from
     */
    public static Set<Archive> findPersistenceArchives(ClassLoader loader, String descriptorPath, List<URL> jarFileUrls, Map properties) {
        Archive archive = null;

        Set<Archive> archives = new HashSet<Archive>();

        // See if we are talking about an embedded descriptor
        // If not embedded descriptor then just use the regular descriptor path
        int splitPosition = descriptorPath.indexOf("!/");
        if (splitPosition != -1) {
            // It is an embedded archive, so split up the parts
            descriptorPath = descriptorPath.substring(splitPosition+2);
        }

        try {
            for(int i=0; i < jarFileUrls.size(); i++) {
                URL puRootUrl = jarFileUrls.get(i);
                archive = PersistenceUnitProcessor.getArchiveFactory(loader, properties).createArchive(puRootUrl, descriptorPath, null);

                // archive = new BundleArchive(puRootUrl, descUrl);
                if (archive != null){
                    archives.add(archive);
                }
            }
        } catch (Exception ex){
            //clean up first
            for (Archive a : archives){
                a.close();
            }
            throw PersistenceUnitLoadingException.exceptionSearchingForPersistenceResources(loader, ex);
        }
        return archives;
    }

    public static Set<SEPersistenceUnitInfo> getPersistenceUnits(ClassLoader loader, Map m, List<URL> jarFileUrls) {
        String descriptorPath = (String) m.get(PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML);
        if(descriptorPath == null) {
            descriptorPath = PrivilegedAccessHelper.getSystemProperty(PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML, PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML_DEFAULT);
        }
        Set<Archive> archives = findPersistenceArchives(loader, descriptorPath, jarFileUrls, m);
        Set<SEPersistenceUnitInfo> puInfos = new HashSet<>();
        try {
            for(Archive archive : archives) {
                List<SEPersistenceUnitInfo> puInfosFromArchive = getPersistenceUnits(archive, loader);
                puInfos.addAll(puInfosFromArchive);
            }
        } finally {
            for(Archive archive : archives) {
                archive.close();
            }
        }
        return puInfos;
    }

    public static ArchiveFactory getArchiveFactory(ClassLoader loader){
        return getArchiveFactory(loader, null);
    }

    public static ArchiveFactory getArchiveFactory(ClassLoader loader, Map properties){
        if (ARCHIVE_FACTORY != null){
            return ARCHIVE_FACTORY;
        }

        ArchiveFactory factory = null;
        String factoryClassName = PrivilegedAccessHelper.shouldUsePrivilegedAccess()
                ? AccessController.doPrivileged(new PrivilegedGetSystemProperty(SystemProperties.ARCHIVE_FACTORY))
                : System.getProperty(SystemProperties.ARCHIVE_FACTORY);

        if (factoryClassName == null && properties != null) {
            Object name = properties.get(SystemProperties.ARCHIVE_FACTORY);
            if(name instanceof String) {
                factoryClassName = (String) name;
            }
        }

        if (factoryClassName == null) {
            return new ArchiveFactoryImpl();
        } else {
            try {
                if (loader != null) {
                    Class<?> archiveClass = loader.loadClass(factoryClassName);
                    if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
                        try {
                            factory = (ArchiveFactory)AccessController.doPrivileged(new PrivilegedNewInstanceFromClass(archiveClass));
                        } catch (PrivilegedActionException exception) {
                            throw PersistenceUnitLoadingException.exceptionCreatingArchiveFactory(factoryClassName, exception);
                        }
                    } else {
                        factory = (ArchiveFactory)PrivilegedAccessHelper.newInstanceFromClass(archiveClass);
                    }
                }
            } catch (ClassNotFoundException cnfe) {
                throw PersistenceUnitLoadingException.exceptionCreatingArchiveFactory(factoryClassName, cnfe);
            } catch (IllegalAccessException iae) {
                throw PersistenceUnitLoadingException.exceptionCreatingArchiveFactory(factoryClassName, iae);
            } catch (InstantiationException ie) {
                throw PersistenceUnitLoadingException.exceptionCreatingArchiveFactory(factoryClassName, ie);
            }
        }

        return factory;
    }

    public static Set<String> getClassNamesFromURL(URL url, ClassLoader loader, Map properties) {
        Set<String> classNames = new HashSet<String>();
        Archive archive = null;
        try {
            archive = PersistenceUnitProcessor.getArchiveFactory(loader, properties).createArchive(url, properties);

            if (archive != null) {
                for (Iterator<String> entries = archive.getEntries(); entries.hasNext();) {
                    String entry = entries.next();
                    if (entry.endsWith(".class")){ // NOI18N
                        classNames.add(buildClassNameFromEntryString(entry));
                    }
                }
            }
        } catch (URISyntaxException e) {
            throw new RuntimeException("url = [" + url + "]", e);  // NOI18N
        } catch (IOException e) {
            throw new RuntimeException("url = [" + url + "]", e);  // NOI18N
        } finally {
            if (archive != null) {
                archive.close();
            }
        }
        return classNames;
    }

    /**
     * Return if a given class is annotated with @Embeddable.
     */
    public static MetadataAnnotation getConverterAnnotation(MetadataClass candidateClass){
        return candidateClass.getAnnotation(JPA_CONVERTER);
    }

    /**
     * Return if a given class is annotated with @Embeddable.
     */
    public static MetadataAnnotation getEmbeddableAnnotation(MetadataClass candidateClass){
        return candidateClass.getAnnotation(JPA_EMBEDDABLE);
    }

    /**
     * Return if a given class is annotated with @Entity.
     */
    public static MetadataAnnotation getEntityAnnotation(MetadataClass candidateClass){
        return candidateClass.getAnnotation(JPA_ENTITY);
    }

    /**
     * Get a list of persistence units from the file or directory at the given
     * url. PersistenceUnits are built based on the presence of a persistence descriptor
     * *
     * @param archive The url of a jar file or directory to check
     */
    public static List<SEPersistenceUnitInfo> getPersistenceUnits(Archive archive, ClassLoader loader){
        return processPersistenceArchive(archive, loader);
    }

    /**
     * Return if a given class is annotated with @Entity.
     */
    public static MetadataAnnotation getMappedSuperclassAnnotation(MetadataClass candidateClass){
        return candidateClass.getAnnotation(JPA_MAPPED_SUPERCLASS);
    }

    /**
     * Return the @StaticMetamodel annotation on the given class.
     */
    public static MetadataAnnotation getStaticMetamodelAnnotation(MetadataClass candidateClass){
        return candidateClass.getAnnotation(JPA_STATIC_METAMODEL);
    }

    /**
     * Return if a given class is annotated with @Converter.
     */
    public static boolean isConverter(MetadataClass candidateClass) {
        return candidateClass.isAnnotationPresent(JPA_CONVERTER);
    }

    /**
     * Return if a given class is annotated with @Embeddable.
     */
    public static boolean isEmbeddable(MetadataClass candidateClass) {
        return candidateClass.isAnnotationPresent(JPA_EMBEDDABLE);
    }

    /**
     * Return if a given class is annotated with @Entity.
     */
    public static boolean isEntity(MetadataClass candidateClass){
        return candidateClass.isAnnotationPresent(JPA_ENTITY);
    }

    /**
     * Return if a given class is annotated with @StaticMetamodel.
     */
    public static boolean isStaticMetamodelClass(MetadataClass candidateClass) {
        return candidateClass.isAnnotationPresent(JPA_STATIC_METAMODEL);
    }


    /**
     * Return if a given class is annotated with @MappedSuperclass.
     */
    public static boolean isMappedSuperclass(MetadataClass candidateClass){
        return candidateClass.isAnnotationPresent(JPA_MAPPED_SUPERCLASS);
    }

    /**
     * Load the given class name with the given class loader.
     */
    public static Class loadClass(String className, ClassLoader loader, boolean throwExceptionIfNotFound, MetadataProject project) {
        Class candidateClass = null;

        try {
            candidateClass = loader.loadClass(className);
        } catch (ClassNotFoundException exc){
            if (throwExceptionIfNotFound){
                throw PersistenceUnitLoadingException.exceptionLoadingClassWhileLookingForAnnotations(className, exc);
            } else {
                AbstractSessionLog.getLog().log(AbstractSessionLog.WARNING, "persistence_unit_processor_error_loading_class", exc.getClass().getName(), exc.getLocalizedMessage() , className);
            }
        } catch (NullPointerException npe) {
            // Bug 227630: If any weavable class is not found in the temporary
            // classLoader - disable weaving
            AbstractSessionLog.getLog().log(AbstractSessionLog.WARNING, AbstractSessionLog.WEAVER, "persistence_unit_processor_error_loading_class_weaving_disabled", loader, project.getPersistenceUnitInfo().getPersistenceUnitName(), className);
            // Disable weaving (for 1->1 and many->1)only if the classLoader
            // returns a NPE on loadClass()
            project.disableWeaving();
        } catch (Exception exception){
            AbstractSessionLog.getLog().log(AbstractSessionLog.WARNING, AbstractSessionLog.WEAVER, "persistence_unit_processor_error_loading_class", exception.getClass().getName(), exception.getLocalizedMessage() , className);
        } catch (Error error){
            AbstractSessionLog.getLog().log(AbstractSessionLog.WARNING, AbstractSessionLog.WEAVER, "persistence_unit_processor_error_loading_class", error.getClass().getName(), error.getLocalizedMessage() , className);
            throw error;
        }

        return candidateClass;
    }

    /**
     * Process the Object/relational metadata from XML and annotations
     */
    public static void processORMetadata(MetadataProcessor processor, boolean throwExceptionOnFail, Mode mode) {
        if (mode == Mode.ALL || mode == Mode.COMPOSITE_MEMBER_INITIAL) {
            // DO NOT CHANGE the order of invocation of various methods.

            // 1 - Load the list of mapping files for the persistence unit. Need to
            // do this before we start processing entities as the list of entity
            // classes depend on metadata read from mapping files.
            processor.loadMappingFiles(throwExceptionOnFail);
        }

        // 2 - Process each XML entity mappings file metadata (except for
        // the actual classes themselves). This method is also responsible
        // for handling any XML merging.
        processor.processEntityMappings(mode);

        // 3 - Process the persistence unit classes (from XML and annotations)
        // and their metadata now.
        processor.processORMMetadata(mode);
    }

    /**
     * Go through the jar file for this PersistenceUnitProcessor and process any
     * XML provided in it.
     */
    public static List<SEPersistenceUnitInfo> processPersistenceArchive(Archive archive, ClassLoader loader){
        URL puRootURL = archive.getRootURL();
        try (InputStream descriptorStream = archive.getDescriptorStream()) {
            return processPersistenceXML(puRootURL, descriptorStream, loader);
          } catch (Exception e) {
            throw PersistenceUnitLoadingException.exceptionLoadingFromUrl(puRootURL.toString(), e);
        }
    }

    /**
     * Build a persistence.xml file into a SEPersistenceUnitInfo object.
     * May eventually change this to use OX mapping as well.
     */
    private static List<SEPersistenceUnitInfo> processPersistenceXML(URL baseURL, InputStream input, ClassLoader loader){
        SAXParserFactory spf = XMLHelper.createParserFactory(false);

        XMLReader xmlReader = null;
        SAXParser sp = null;
        XMLExceptionHandler xmlErrorHandler = new XMLExceptionHandler();
        // 247735 - remove the validation of XML.

        // create a SAX parser
        try {
            sp = spf.newSAXParser();
        } catch (ParserConfigurationException | SAXException exc){
            throw XMLParseException.exceptionCreatingSAXParser(baseURL, exc);
        }

        // create an XMLReader
        try {
            xmlReader = sp.getXMLReader();
            xmlReader.setErrorHandler(xmlErrorHandler);
        } catch (org.xml.sax.SAXException exc){
            throw XMLParseException.exceptionCreatingXMLReader(baseURL, exc);
        }

        PersistenceContentHandler myContentHandler = new PersistenceContentHandler();
        xmlReader.setContentHandler(myContentHandler);

        InputSource inputSource = new InputSource(input);
        try{
            xmlReader.parse(inputSource);
        } catch (IOException exc){
            throw PersistenceUnitLoadingException.exceptionProcessingPersistenceXML(baseURL, exc);
        } catch (org.xml.sax.SAXException exc){
            // XMLErrorHandler will handle SAX exceptions
        }

        // handle any parse exceptions
        XMLException xmlError = xmlErrorHandler.getXMLException();
        if (xmlError != null) {
            throw PersistenceUnitLoadingException.exceptionProcessingPersistenceXML(baseURL, xmlError);
        }

        Iterator<SEPersistenceUnitInfo> persistenceInfos = myContentHandler.getPersistenceUnits().iterator();
        while (persistenceInfos.hasNext()){
            SEPersistenceUnitInfo info = persistenceInfos.next();
            info.setPersistenceUnitRootUrl(baseURL);
            info.setClassLoader(loader);
            info.setNewTempClassLoader(loader);
        }
        return myContentHandler.getPersistenceUnits();
    }

    public static void setArchiveFactory(ArchiveFactory factory){
        ARCHIVE_FACTORY = factory;
    }

    /**
     * Build the unique persistence name by concatenating the decoded URL with the persistence unit name.
     * A decoded URL is required while persisting on a multi-bytes OS.
     * @param url
     * @param puName
     * @return String
     */
   public static String buildPersistenceUnitName(URL url, String puName){
       String fullPuName = null;
       try {
           // append the persistence unit name to the decoded URL
           fullPuName = URLDecoder.decode(url.toString(), "UTF8")+"_"+puName;
       } catch (UnsupportedEncodingException e) {
           throw PersistenceUnitLoadingException.couldNotBuildPersistenceUntiName(e,url.toString(),puName);
       }
       return fullPuName;
   }

    /**
     * @param file archive file URL. In case of a nested archive, this is
     * the URL of the innermost archive.
     * @param rootEntry a directory entry in the archive (or an empty string).
     * In case of a nested archive, this is the entry in the innermost archive.
     * @return true if the file-entry pair can be a persistence root according
     * to JPA Spec (8.2).
     */
    private static boolean isValidRootInArchive(String file, String rootEntry) {
        String extension = file.substring(Math.max(0, file.length() - 4));
        if (extension.equalsIgnoreCase(".jar")) {
            // For a JAR, the root can only be the archive itself.
            return rootEntry.isEmpty();
        } else if (extension.equalsIgnoreCase(".war")) {
            // For a WAR, the root can be:
            // 1. WEB-INF/classes
            // 2. One of a JARs inside the WEB-INF/lib
            // In the second case rootEntry is the entry in the innermost
            // archive, and file is the URL of that archive. Since
            // the innermost archive has to be a JAR (according to JPA Spec),
            // this case is handled by the previous branch.
            return rootEntry.equals(WEBINF_CLASSES_STR);
        } else {
            return false;
        }
    }
}
