/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.openjpa.persistence;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Set;

import javax.persistence.SharedCacheMode;
import javax.persistence.ValidationMode;
import javax.persistence.spi.PersistenceUnitInfo;
import javax.persistence.spi.PersistenceUnitTransactionType;

import org.apache.openjpa.conf.Compatibility;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.conf.OpenJPAConfigurationImpl;
import org.apache.openjpa.conf.OpenJPAProductDerivation;
import org.apache.openjpa.conf.Specification;
import org.apache.openjpa.datacache.DataCacheMode;
import org.apache.openjpa.kernel.MixedLockLevels;
import org.apache.openjpa.kernel.QueryHints;
import org.apache.openjpa.lib.conf.AbstractProductDerivation;
import org.apache.openjpa.lib.conf.Configuration;
import org.apache.openjpa.lib.conf.ConfigurationProvider;
import org.apache.openjpa.lib.conf.Configurations;
import org.apache.openjpa.lib.conf.MapConfigurationProvider;
import org.apache.openjpa.lib.conf.ProductDerivations;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.meta.XMLMetaDataParser;
import org.apache.openjpa.lib.meta.XMLVersionParser;
import org.apache.openjpa.lib.util.J2DoPrivHelper;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.MultiClassLoader;
import org.apache.openjpa.lib.util.StringUtil;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;


/**
 * Sets JPA specification defaults and parses JPA specification XML files.
 *
 * For globals, looks in <code>openjpa.properties</code> system property for
 * the location of a file to parse. If no system property is defined, the
 * default resource location of <code>META-INF/openjpa.xml</code> is used.
 *
 * For defaults, looks for <code>META-INF/persistence.xml</code>.
 * Within <code>persistence.xml</code>, look for the named persistence unit, or
 * if no name given, an OpenJPA unit (preferring an unnamed OpenJPA unit to
 * a named one).
 *
 * @author Abe White
 */
public class PersistenceProductDerivation
    extends AbstractProductDerivation
    implements OpenJPAProductDerivation {

    public static final Specification SPEC_JPA = new Specification("jpa 2");
    public static final Specification ALIAS_EJB = new Specification("ejb 3");
    public static final String RSRC_GLOBAL = "META-INF/openjpa.xml";
    public static final String RSRC_DEFAULT = "META-INF/persistence.xml";
    public static final BigDecimal VERSION_1_0 = BigDecimal.valueOf(1.0);

    private static final Localizer _loc = Localizer.forPackage
        (PersistenceProductDerivation.class);

    private HashMap<String, PUNameCollision> _puNameCollisions
        = new HashMap<>();

    public static final String PREFIX = "javax.persistence";

    // These are properties that are invalid to be configured at the provider level.
    private static final String[] _invalidPersistenceProperties =
        new String[] { PREFIX + ".cache.storeMode", PREFIX + ".cache.retrieveMode" };

    private static Set<String> _hints = new HashSet<>();

    // Provider name to filter out PUs that don't belong to this derivation.
    protected String _providerImplName;

    static {
        _hints.add("javax.persistence.lock.timeout");
        _hints.add("javax.persistence.query.timeout");

        _hints.add("openjpa.FetchPlan.ExtendedPathLookup");
        _hints.add("openjpa.FetchBatchSize");
        _hints.add("openjpa.FetchPlan.FetchBatchSize");
        _hints.add("openjpa.MaxFetchDepth");
        _hints.add("openjpa.FetchPlan.MaxFetchDepth");
        _hints.add("openjpa.LockTimeout");
        _hints.add("openjpa.FetchPlan.LockTimeout");
        _hints.add("openjpa.QueryTimeout");
        _hints.add("openjpa.FetchPlan.QueryTimeout");
        _hints.add("openjpa.FlushBeforeQueries");
        _hints.add("openjpa.FetchPlan.FlushBeforeQueries");
        _hints.add("openjpa.ReadLockLevel");
        _hints.add("openjpa.FetchPlan.ReadLockLevel");
        _hints.add("openjpa.WriteLockLevel");
        _hints.add("openjpa.FetchPlan.WriteLockLevel");
        _hints.add("openjpa.FetchPlan.FetchBatchSize");
        _hints.add("openjpa.FetchPlan.LockScope");
        _hints.add("openjpa.FetchPlan.LockTimeout");
        _hints.add("openjpa.FetchPlan.MaxFetchDepth");
        _hints.add("openjpa.FetchPlan.QueryTimeout");
        _hints.add("openjpa.FetchPlan.ReadLockMode");
        _hints.add("openjpa.FetchPlan.WriteLockMode");
        _hints.add(QueryHints.HINT_AGGREGATE_LISTENER);
        _hints.add(QueryHints.HINT_AGGREGATE_LISTENERS);
        _hints.add(QueryHints.HINT_FILTER_LISTENER);
        _hints.add(QueryHints.HINT_FILTER_LISTENERS);
        _hints.add(QueryHints.HINT_IGNORE_FINDER);
        _hints.add(QueryHints.HINT_IGNORE_PREPARED_QUERY);
        _hints.add(QueryHints.HINT_INVALIDATE_FINDER);
        _hints.add(QueryHints.HINT_INVALIDATE_PREPARED_QUERY);
        _hints.add(QueryHints.HINT_PARAM_MARKER_IN_QUERY);
        _hints.add(QueryHints.HINT_RECACHE_FINDER);
        _hints.add(QueryHints.HINT_RESULT_COUNT);
        _hints.add(QueryHints.HINT_SUBCLASSES);
        _hints.add(QueryHints.HINT_RELAX_BIND_PARAM_TYPE_CHECK);
        _hints.add(QueryHints.HINT_USE_LITERAL_IN_SQL);

        _hints = Collections.unmodifiableSet(_hints);
    }

	public PersistenceProductDerivation() {
		_providerImplName = PersistenceProviderImpl.class.getName();
	}

    @Override
    public void putBrokerFactoryAliases(Map<String, String> m) {
    }

    @Override
    public int getType() {
        return TYPE_SPEC;
    }

    @Override
    public String getConfigurationPrefix() {
        return PREFIX;
    }

    @Override
    public Set<String> getSupportedQueryHints() {
        return _hints;
    }

    @Override
    public void validate()
        throws Exception {
        // make sure JPA is available
        AccessController.doPrivileged(J2DoPrivHelper.getClassLoaderAction(
            javax.persistence.EntityManagerFactory.class));
    }

    @Override
    public boolean beforeConfigurationLoad(Configuration c) {
        if (!(c instanceof OpenJPAConfigurationImpl))
            return false;

        OpenJPAConfigurationImpl conf = (OpenJPAConfigurationImpl) c;
        conf.metaFactoryPlugin.setAlias(ALIAS_EJB.getName(), PersistenceMetaDataFactory.class.getName());
        conf.metaFactoryPlugin.setAlias(SPEC_JPA.getName(),  PersistenceMetaDataFactory.class.getName());

        conf.addValue(new EntityManagerFactoryValue());

        conf.readLockLevel.setAlias("optimistic", String.valueOf(MixedLockLevels.LOCK_OPTIMISTIC));
        conf.readLockLevel.setAlias("optimistic-force-increment", String
            .valueOf(MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT));
        conf.readLockLevel.setAlias("pessimistic-read", String
            .valueOf(MixedLockLevels.LOCK_PESSIMISTIC_READ));
        conf.readLockLevel.setAlias("pessimistic-write", String
            .valueOf(MixedLockLevels.LOCK_PESSIMISTIC_WRITE));
        conf.readLockLevel.setAlias("pessimistic-force-increment", String
            .valueOf(MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT));

        conf.writeLockLevel.setAlias("optimistic", String
            .valueOf(MixedLockLevels.LOCK_OPTIMISTIC));
        conf.writeLockLevel.setAlias("optimistic-force-increment", String
            .valueOf(MixedLockLevels.LOCK_OPTIMISTIC_FORCE_INCREMENT));
        conf.writeLockLevel.setAlias("pessimistic-read", String
            .valueOf(MixedLockLevels.LOCK_PESSIMISTIC_READ));
        conf.writeLockLevel.setAlias("pessimistic-write", String
            .valueOf(MixedLockLevels.LOCK_PESSIMISTIC_WRITE));
        conf.writeLockLevel.setAlias("pessimistic-force-increment", String
            .valueOf(MixedLockLevels.LOCK_PESSIMISTIC_FORCE_INCREMENT));


        configureBeanValidation(conf);

        conf.dataCacheMode = conf.addString(JPAProperties.CACHE_MODE);
        conf.dataCacheMode.setDefault(DataCacheMode.UNSPECIFIED.toString());
        conf.dataCacheMode.set(DataCacheMode.UNSPECIFIED.toString());

        return true;
    }

    /**
     * Bean Validation configuration is unusual because its usage of enums and keys that
     * do not have counterparts in kernel.
     * Hence the plugins are defined in product derivation instead of the kernel's
     * core configuration.
     *
     * @param conf
     */
    private void configureBeanValidation(OpenJPAConfigurationImpl conf) {
        // Validation defines/adds the following plugins to OpenJPA Configuration
        conf.validationFactory         = conf.addObject(JPAProperties.VALIDATE_FACTORY);
        conf.validator                 = conf.addObject("Validator");
        conf.validationMode            = conf.addString(JPAProperties.VALIDATE_MODE);
        conf.validationGroupPrePersist = conf.addString(JPAProperties.VALIDATE_PRE_PERSIST);
        conf.validationGroupPreUpdate  = conf.addString(JPAProperties.VALIDATE_PRE_UPDATE);
        conf.validationGroupPreRemove  = conf.addString(JPAProperties.VALIDATE_PRE_REMOVE);

        conf.validationMode.setDynamic(true);
        String[] aliases = new String[] {
                String.valueOf(ValidationMode.AUTO),
                String.valueOf(ValidationMode.AUTO).toLowerCase(Locale.ENGLISH),
                String.valueOf(ValidationMode.CALLBACK),
                String.valueOf(ValidationMode.CALLBACK).toLowerCase(Locale.ENGLISH),
                String.valueOf(ValidationMode.NONE),
                String.valueOf(ValidationMode.NONE).toLowerCase(Locale.ENGLISH)
        };
        conf.validationMode.setAliases(aliases);
        conf.validationMode.setAliasListComprehensive(true);
        conf.validationMode.setDefault(aliases[0]);

        conf.validationGroupPrePersist.setString(JPAProperties.VALIDATE_GROUP_DEFAULT);
        conf.validationGroupPrePersist.setDefault("");
        conf.validationGroupPrePersist.setDynamic(true);

        conf.validationGroupPreUpdate.setString(JPAProperties.VALIDATE_GROUP_DEFAULT);
        conf.validationGroupPreUpdate.setDefault("");
        conf.validationGroupPreUpdate.setDynamic(true);

        conf.validationGroupPreRemove.setDefault("");
        conf.validationGroupPreRemove.setDynamic(true);

        conf.validationFactory.setInstantiatingGetter("getValidationFactoryInstance");
        conf.validationFactory.setDynamic(true);

        conf.validator.setInstantiatingGetter("getValidatorInstance");
        conf.validator.setDynamic(true);
        conf.validator.makePrivate();
    }

    @Override
    public boolean afterSpecificationSet(Configuration c) {
        if (!OpenJPAConfigurationImpl.class.isInstance(c)
         && !SPEC_JPA.isSame(((OpenJPAConfiguration) c).getSpecification()))
            return false;

        OpenJPAConfigurationImpl conf = (OpenJPAConfigurationImpl) c;
        conf.metaFactoryPlugin.setDefault(SPEC_JPA.getName());
        conf.metaFactoryPlugin.setString(SPEC_JPA.getName());
        conf.nontransactionalWrite.setDefault("true");
        conf.nontransactionalWrite.set(true);
        Specification spec = ((OpenJPAConfiguration) c).getSpecificationInstance();
        int specVersion = spec.getVersion();
        Compatibility compatibility = conf.getCompatibilityInstance();
        spec.setCompatibility(compatibility);
        if (specVersion < 2) {
            compatibility.setFlushBeforeDetach(true);
            compatibility.setCopyOnDetach(true);
            compatibility.setPrivatePersistentProperties(true);
            compatibility.setIgnoreDetachedStateFieldForProxySerialization(true);
            // Disable bean validation for spec level < 2 configurations
            conf.validationMode.set(String.valueOf(ValidationMode.NONE));
        } else {
            compatibility.setAbstractMappingUniDirectional(true);
            compatibility.setNonDefaultMappingAllowed(true);
        }
        return true;
    }

    /**
     * Load configuration from the given persistence unit with the specified
     * user properties.
     */
    public ConfigurationProvider load(PersistenceUnitInfo pinfo, Map m)
        throws IOException {
        if (pinfo == null)
            return null;
        if (!isOpenJPAPersistenceProvider(pinfo, null)) {
            warnUnknownProvider(pinfo);
            return null;
        }

        ConfigurationProviderImpl cp = new ConfigurationProviderImpl();
        cp.addProperties(PersistenceUnitInfoImpl.toOpenJPAProperties(pinfo));
        cp.addProperties(m);
        if (pinfo instanceof PersistenceUnitInfoImpl) {
            PersistenceUnitInfoImpl impl = (PersistenceUnitInfoImpl) pinfo;
            if (impl.getPersistenceXmlFileUrl() != null)
                cp.setSource(impl.getPersistenceXmlFileUrl().toString());
        }
        return cp;
    }

    /**
     * Load configuration from the given resource and unit names, which may
     * be null.
     */
    public ConfigurationProvider load(String rsrc, String name, Map m)
        throws IOException {
        boolean explicit = !StringUtil.isEmpty(rsrc);
        if (!explicit)
            rsrc = RSRC_DEFAULT;

        ConfigurationProviderImpl cp = new ConfigurationProviderImpl();
        Boolean ret = load(cp, rsrc, name, m, null, explicit);
        if (ret != null)
            return (ret) ? cp : null;
        if (explicit)
            return null;

        // persistence.xml does not exist; just load map
        PersistenceUnitInfoImpl pinfo = new PersistenceUnitInfoImpl();
        pinfo.fromUserProperties(m);
        if (!isOpenJPAPersistenceProvider(pinfo, null)) {
            warnUnknownProvider(pinfo);
            return null;
        }
        cp.addProperties(pinfo.toOpenJPAProperties());
        return cp;
    }

    @Override
    public ConfigurationProvider load(String rsrc, String anchor,
        ClassLoader loader)
        throws IOException {
        if (rsrc != null && !rsrc.endsWith(".xml"))
            return null;
        ConfigurationProviderImpl cp = new ConfigurationProviderImpl();
        if (load(cp, rsrc, anchor, null, loader, true) == Boolean.TRUE)
            return cp;
        return null;
    }

    @Override
    public ConfigurationProvider load(File file, String anchor)
        throws IOException {
        if (!file.getName().endsWith(".xml"))
            return null;

        ConfigurationParser parser = new ConfigurationParser(null);
        parser.parse(file);
        return load(findUnit((List<PersistenceUnitInfoImpl>)
            parser.getResults(), anchor, null), null);
    }

    @Override
    public String getDefaultResourceLocation() {
        return RSRC_DEFAULT;
    }

    @Override
    public List<String> getAnchorsInFile(File file) throws IOException {
        ConfigurationParser parser = new ConfigurationParser(null);
        try {
            parser.parse(file);
            return getUnitNames(parser);
        } catch (IOException e) {
            // not all configuration files are XML; return null if unparsable
            return null;
        }
    }

    private List<String> getUnitNames(ConfigurationParser parser) {
        List<PersistenceUnitInfoImpl> units = parser.getResults();
        List<String> names = new ArrayList<>();
        for (PersistenceUnitInfoImpl unit : units){
        	String provider = unit.getPersistenceProviderClassName();
			// Only add the PU name if the provider it is ours or not specified.
			if (provider == null || provider.equals(_providerImplName)) {
				names.add(unit.getPersistenceUnitName());
			} else {
				// Should trace something, but logging isn't configured yet.
				// Swallow.
			}
        }
        return names;
    }

    @Override
    public List getAnchorsInResource(String resource) throws Exception {
        ConfigurationParser parser = new ConfigurationParser(null);
        try {
        	List results = new ArrayList();
            ClassLoader loader = AccessController.doPrivileged(
                J2DoPrivHelper.getContextClassLoaderAction());
            List<URL> urls = getResourceURLs(resource, loader);
            if (urls != null) {
                for (URL url : urls) {
                    parser.parse(url);
                    results.addAll(getUnitNames(parser));
                }
            }
            return results;
        } catch (IOException e) {
            // not all configuration files are XML; return null if unparsable
            return null;
        }
    }

    @Override
    public ConfigurationProvider loadGlobals(ClassLoader loader)
        throws IOException {
        String[] prefixes = ProductDerivations.getConfigurationPrefixes();
        String rsrc = null;
        for (int i = 0; i < prefixes.length && StringUtil.isEmpty(rsrc); i++)
           rsrc = AccessController.doPrivileged(J2DoPrivHelper
                .getPropertyAction(prefixes[i] + ".properties"));
        boolean explicit = !StringUtil.isEmpty(rsrc);
        String anchor = null;
        int idx = (!explicit) ? -1 : rsrc.lastIndexOf('#');
        if (idx != -1) {
            // separate name from <resrouce>#<name> string
            if (idx < rsrc.length() - 1)
                anchor = rsrc.substring(idx + 1);
            rsrc = rsrc.substring(0, idx);
        }
        if (StringUtil.isEmpty(rsrc))
            rsrc = RSRC_GLOBAL;
        else if (!rsrc.endsWith(".xml"))
            return null;

        ConfigurationProviderImpl cp = new ConfigurationProviderImpl();
        if (load(cp, rsrc, anchor, null, loader, explicit) == Boolean.TRUE)
            return cp;
        return null;
    }

    @Override
    public ConfigurationProvider loadDefaults(ClassLoader loader)
        throws IOException {
        ConfigurationProviderImpl cp = new ConfigurationProviderImpl();
        if (load(cp, RSRC_DEFAULT, null, null, loader, false) == Boolean.TRUE)
            return cp;
        return null;
    }

      /**
      * This method checks to see if the provided <code>puName</code> was
      * detected in multiple resources. If a collision is detected, a warning
      * will be logged and this method will return <code>true</code>.
      * <p>
      */
     public boolean checkPuNameCollisions(Log logger,String puName){
         PUNameCollision p = _puNameCollisions.get(puName);
         if (p != null){
             p.logCollision(logger);
             return true;
         }
         return false;
     }

    private static List<URL> getResourceURLs(String rsrc, ClassLoader loader)
        throws IOException {
        Enumeration<URL> urls = null;
        try {
            urls = AccessController.doPrivileged(J2DoPrivHelper.getResourcesAction(loader, rsrc));
            if (!urls.hasMoreElements()) {
                if (!rsrc.startsWith("META-INF"))
                  urls = AccessController.doPrivileged(J2DoPrivHelper.getResourcesAction(loader, "META-INF/" + rsrc));
                if (!urls.hasMoreElements())
                    return null;
            }
        } catch (PrivilegedActionException pae) {
            throw (IOException) pae.getException();
        }

        return Collections.list(urls);
    }

    /**
     * Looks through the resources at <code>rsrc</code> for a configuration
     * file that matches <code>name</code> (or an unnamed one if
     * <code>name</code> is <code>null</code>), and loads the XML in the
     * resource into a new {@link PersistenceUnitInfo}. Then, applies the
     * overrides in <code>m</code>.
     *
     * @return {@link Boolean#TRUE} if the resource was loaded, null if it
     * does not exist, or {@link Boolean#FALSE} if it is not for OpenJPA
     */
    private Boolean load(ConfigurationProviderImpl cp, String rsrc,
        String name, Map m, ClassLoader loader, boolean explicit)
        throws IOException {
        ClassLoader contextLoader = null;
        if (loader == null) {
            contextLoader = AccessController.doPrivileged(J2DoPrivHelper.getContextClassLoaderAction());
            loader = contextLoader;
        }

        List<URL> urls = getResourceURLs(rsrc, loader);
        if (urls == null || urls.size() == 0)
            return null;

        ConfigurationParser parser = new ConfigurationParser(m);
        PersistenceUnitInfoImpl pinfo = parseResources(parser, urls, name, loader);
        if (pinfo == null) {
            if (!explicit)
                return Boolean.FALSE;
            throw new MissingResourceException(_loc.get("missing-xml-config",
                rsrc, String.valueOf(name)).getMessage(), getClass().getName(), rsrc);
        } else if (!isOpenJPAPersistenceProvider(pinfo, loader)) {
            if (!explicit) {
                warnUnknownProvider(pinfo);
                return Boolean.FALSE;
            }
            throw new MissingResourceException(_loc.get("unknown-provider",
                rsrc, name, pinfo.getPersistenceProviderClassName()).
                getMessage(), getClass().getName(), rsrc);
        }

        // Process jar-file references after confirming OpenJPA is the desired JPA provider.
        if ( loader != contextLoader && loader instanceof MultiClassLoader) {
            // combine the MultiClassLoader and set to the context
            // so that it could be used in the jar validation
            MultiClassLoader mutliClassLoader = (MultiClassLoader) loader;
            contextLoader = (contextLoader != null) ? contextLoader
                    : AccessController.doPrivileged(J2DoPrivHelper.getContextClassLoaderAction());
            mutliClassLoader.addClassLoader(contextLoader);
            AccessController.doPrivileged(J2DoPrivHelper.setContextClassLoaderAction(mutliClassLoader));
        }
        pinfo.processJarFileNames();

        if (contextLoader != null) {
            //restore the context loader
            AccessController.doPrivileged(J2DoPrivHelper.setContextClassLoaderAction(contextLoader));
        }

        cp.addProperties(pinfo.toOpenJPAProperties());
        cp.setSource(pinfo.getPersistenceXmlFileUrl().toString());
        return Boolean.TRUE;
    }

    /**
     * Parse resources at the given location. Searches for a
     * PersistenceUnitInfo with the requested name, or an OpenJPA unit if
     * no name given (preferring an unnamed OpenJPA unit to a named one).
     */
    private PersistenceUnitInfoImpl parseResources(ConfigurationParser parser,
        List<URL> urls, String name, ClassLoader loader)
        throws IOException {
        List<PersistenceUnitInfoImpl> pinfos = new ArrayList<>();
        for (URL url : urls) {
            parser.parse(url);
            pinfos.addAll((List<PersistenceUnitInfoImpl>) parser.getResults());
        }
        return findUnit(pinfos, name, loader);
    }

    /**
     * Find the unit with the given name, or an OpenJPA unit if no name is
     * given (preferring an unnamed OpenJPA unit to a named one).
     */
    private PersistenceUnitInfoImpl findUnit(List<PersistenceUnitInfoImpl>
        pinfos, String name, ClassLoader loader) {
        PersistenceUnitInfoImpl ojpa = null;
        PersistenceUnitInfoImpl result = null;
        for (PersistenceUnitInfoImpl pinfo : pinfos) {
            // found named unit?
            if (name != null) {
                if (name.equals(pinfo.getPersistenceUnitName())){
                    if (result != null){
                        this.addPuNameCollision(name, result.getPersistenceXmlFileUrl().toString(),
                                pinfo.getPersistenceXmlFileUrl().toString());

                    } else {
                        // Grab a ref to the pinfo that matches the name we're
                        // looking for. Keep going to look for duplicate pu names.
                        result = pinfo;
                    }
                }
                continue;
            }

            if (isOpenJPAPersistenceProvider(pinfo, loader)) {
                // if no name given and found unnamed unit, return it.
                // otherwise record as default unit unless we find a better match later
                if (StringUtil.isEmpty(pinfo.getPersistenceUnitName()))
                    return pinfo;
                if (ojpa == null)
                    ojpa = pinfo;
            }
        }
        if(result!=null){
            return result;
        }
        return ojpa;
    }

    /**
     * Return whether the given persistence unit uses an OpenJPA provider.
     */
    private static boolean isOpenJPAPersistenceProvider(PersistenceUnitInfo pinfo, ClassLoader loader) {
        String provider = pinfo.getPersistenceProviderClassName();
        if (StringUtil.isEmpty(provider) || PersistenceProviderImpl.class.getName().equals(provider))
            return true;

        if (loader == null)
            loader = AccessController.doPrivileged(J2DoPrivHelper.getContextClassLoaderAction());
        try {
            if (PersistenceProviderImpl.class.isAssignableFrom(Class.forName(provider, false, loader)))
                return true;
        } catch (Throwable t) {
            log(_loc.get("unloadable-provider", provider, t).getMessage());
            return false;
        }
        return false;
    }

    /**
     * Warn the user that we could only find an unrecognized persistence
     * provider.
     */
    private static void warnUnknownProvider(PersistenceUnitInfo pinfo) {
        log(_loc.get("unrecognized-provider", pinfo.getPersistenceProviderClassName()).getMessage());
    }

    /**
     * Log a message.
     */
    private static void log(String msg) {
        // at this point logging isn't configured yet
        // START - ALLOW PRINT STATEMENTS
        System.err.println(msg);
        // STOP - ALLOW PRINT STATEMENTS
    }

    private void addPuNameCollision(String puName, String file1, String file2){
        PUNameCollision pun = _puNameCollisions.get(puName);
        if (pun != null){
            pun.addCollision(file1, file2);
        } else {
            _puNameCollisions.put(puName, new PUNameCollision(puName, file1, file2));
        }
    }

    /**
     * Custom configuration provider.
     */
    public static class ConfigurationProviderImpl
        extends MapConfigurationProvider {

        private String _source;

        public ConfigurationProviderImpl() {
        }

        public ConfigurationProviderImpl(Map props) {
            super(props);
        }

        /**
         * Set the source of information in this provider.
         */
        public void setSource(String source) {
            _source = source;
        }

        @Override
        public void setInto(Configuration conf) {
            if (conf instanceof OpenJPAConfiguration) {
                OpenJPAConfiguration oconf = (OpenJPAConfiguration) conf;
                Object persistenceVersion = getProperties().get(PersistenceUnitInfoImpl.PERSISTENCE_VERSION);
                if (persistenceVersion == null) {
                    oconf.setSpecification(SPEC_JPA);
                } else {
                    // Set the spec level based on the persistence version
                    oconf.setSpecification("jpa " + persistenceVersion.toString());
                }


                // we merge several persistence.xml elements into the
                // MetaDataFactory property implicitly.  if the user has a
                // global openjpa.xml with this property set, its value will
                // get overwritten by our implicit setting.  so instead, combine
                // the global value with our settings
                String orig = oconf.getMetaDataFactory();
                if (!StringUtil.isEmpty(orig)) {
                    String key = ProductDerivations.getConfigurationKey("MetaDataFactory", getProperties());
                    Object override = getProperties().get(key);
                    if (override instanceof String)
                        addProperty(key, Configurations.combinePlugins(orig, (String) override));
                }
            }
            super.setInto(conf, null);

            // At this point user properties have been loaded into the configuration. Apply any modifications based off
            // those.
            if (conf instanceof OpenJPAConfiguration) {
                OpenJPAConfiguration oconf = (OpenJPAConfiguration) conf;
                String dataCache = oconf.getDataCache();
                String sharedDataCacheMode = oconf.getDataCacheMode();

                if (DataCacheMode.NONE.toString().equals(sharedDataCacheMode)
                        && dataCache != null && !"false".equals(dataCache)) {
                    Log log = conf.getConfigurationLog();
                    if (log.isWarnEnabled()) {
                        log.warn(_loc.get("shared-cache-mode-take-precedence", dataCache));
                    }
                }

                if ((dataCache == null || "false".equals(dataCache))
                        && !DataCacheMode.NONE.toString().equals(sharedDataCacheMode)
                        && !DataCacheMode.UNSPECIFIED.toString().equals(sharedDataCacheMode)){
                    oconf.setDataCache("true");
                }

                // If the datacache is enabled, make sure we have a RemoteCommitProvider
                String rcp = oconf.getRemoteCommitProvider();
                dataCache = oconf.getDataCache();
                // If the datacache is set and is something other than false
                if (dataCache != null && !"false".equals(dataCache)) {
                    // If RCP is null or empty, set it to sjvm.
                    if (rcp == null || "".equals(rcp)) {
                        oconf.setRemoteCommitProvider("sjvm");
                    }
                }
            }

            Log log = conf.getConfigurationLog();
            if (log.isWarnEnabled()) {
                Map<?, ?> props = getProperties();
                for (String propKey : _invalidPersistenceProperties) {
                    Object propValue = props.get(propKey);
                    if (propValue != null) {
                        log.warn(_loc.get("invalid-persistence-property", new Object[] { propKey, propValue }));
                    }
                }
            }
            if (log.isTraceEnabled()) {
                String src = (_source == null) ? "?" : _source;
                log.trace(_loc.get("conf-load", src, getProperties()));
            }
        }
    }

    /**
     * SAX handler capable of parsing an JPA persistence.xml file.
     * Package-protected for testing.
     */
    public static class ConfigurationParser
        extends XMLMetaDataParser {

        private static final String PERSISTENCE_XSD_2_0 = "persistence_2_0.xsd";
        private static final String PERSISTENCE_XSD_2_1 = "persistence_2_1.xsd";

        private static final Localizer _loc = Localizer.forPackage
            (ConfigurationParser.class);

        private final Map _map;
        private PersistenceUnitInfoImpl _info = null;
        private URL _source = null;
        private String _persistenceVersion;
        private String _schemaLocation;
        private boolean _excludeUnlistedSet = false;

        public ConfigurationParser(Map map) {
            _map = map;
            setCaching(false);
            setValidating(true);
            setParseText(true);
        }

        @Override
        public void parse(URL url)
            throws IOException {
            _source = url;

            // peek at the doc to determine the version
            XMLVersionParser vp = new XMLVersionParser("persistence");
            try {
                vp.parse(url);
                _persistenceVersion = vp.getVersion();
                _schemaLocation = vp.getSchemaLocation();
            } catch (Throwable t) {
                    log(_loc.get("version-check-error",
                        _source.toString()).toString());
            }
            super.parse(url);
        }

        @Override
        public void parse(File file)
            throws IOException {
            try {
                _source = AccessController.doPrivileged(J2DoPrivHelper
                    .toURLAction(file));
            } catch (PrivilegedActionException pae) {
                throw (MalformedURLException) pae.getException();
            }
            // peek at the doc to determine the version
            XMLVersionParser vp = new XMLVersionParser("persistence");
            try {
                vp.parse(file);
                _persistenceVersion = vp.getVersion();
                _schemaLocation = vp.getSchemaLocation();
            } catch (Throwable t) {
                log(_loc.get("version-check-error", _source.toString()).toString());
            }
            super.parse(file);
        }

        @Override
        protected Object getSchemaSource() {
            // use the version 1 schema by default.  non-versioned docs will
            // continue to parse with the old xml if they do not contain a
            // persistence-unit.  that is currently the only significant change
            // to the schema.  if more significant changes are made in the
            // future, the 2.0 schema may be preferable.
            String persistencexsd = "persistence-xsd.rsrc";
            // if the version and/or schema location is for 1.0, use the 1.0
            // schema
            if (XMLVersionParser.VERSION_2_0.equals(_persistenceVersion)
                    || (_schemaLocation != null && _schemaLocation.indexOf(PERSISTENCE_XSD_2_0) != -1))
            {
                persistencexsd = "persistence_2_0-xsd.rsrc";
            } else if (XMLVersionParser.VERSION_2_1.equals(_persistenceVersion)
                    || (_schemaLocation != null && _schemaLocation.indexOf(PERSISTENCE_XSD_2_1) != -1))
            {
                persistencexsd = "persistence_2_1-xsd.rsrc";
            }
            return getClass().getResourceAsStream(persistencexsd);
        }

        @Override
        protected void reset() {
            super.reset();
            _info = null;
            _source = null;
            _excludeUnlistedSet = false;
        }

        @Override
        protected boolean startElement(String name, Attributes attrs)
            throws SAXException {
            if (currentDepth() == 1)
                startPersistenceUnit(attrs);
            else if (currentDepth() == 3 && "property".equals(name))
                _info.setProperty(attrs.getValue("name"), attrs.getValue("value"));
            return true;
        }

        @Override
        protected void endElement(String name)
            throws SAXException {
            if (currentDepth() == 1) {
                endPersistenceUnit();
                _info.fromUserProperties(_map);
                addResult(_info);
            }
            if (currentDepth() != 2)
                return;

            switch (name.charAt(0)) {
                // cases 'name' and 'transaction-type' are handled in
                //      startPersistenceUnit()
                // case 'property' for 'properties' is handled in startElement()
                case 'c': // class
                    _info.addManagedClassName(currentText());
                    break;
                case 'e': // exclude-unlisted-classes
                    setExcludeUnlistedClasses(currentText());
                    break;
                case 'j':
                    if ("jta-data-source".equals(name))
                        _info.setJtaDataSourceName(currentText());
                    else { // jar-file
                        try {
                            _info.addJarFileName(currentText());
                        } catch (IllegalArgumentException iae) {
                            throw getException(iae.getMessage());
                        }
                    }
                    break;
                case 'm': // mapping-file
                    _info.addMappingFileName(currentText());
                    break;
                case 'n': // non-jta-data-source
                    _info.setNonJtaDataSourceName(currentText());
                    break;
                case 'p':
                    if ("provider".equals(name))
                        _info.setPersistenceProviderClassName(currentText());
                    break;
                case 's' : // shared-cache-mode
                    _info.setSharedCacheMode(JPAProperties.getEnumValue(SharedCacheMode.class, currentText()));
                    break;
                case 'v': // validation-mode
                    _info.setValidationMode(JPAProperties.getEnumValue(ValidationMode.class, currentText()));
                    break;
            }
        }

        // The default value for exclude-unlisted-classes was
        // modified in JPA 2.0 from false to true.  Set the default
        // based upon the persistence version to preserve behavior
        // of pre-JPA 2.0 applications.
        private void setExcludeUnlistedClasses(String value) {
            if (!_excludeUnlistedSet) {
                BigDecimal version = getPersistenceVersion();
                boolean excludeUnlisted;
                if (version.compareTo(VERSION_1_0) > 0) {
                    excludeUnlisted = !("false".equalsIgnoreCase(value));
                } else {
                    excludeUnlisted = "true".equalsIgnoreCase(value);
                }
                _info.setExcludeUnlistedClasses(excludeUnlisted);
                _excludeUnlistedSet = true;
            }
        }

        /**
         * Parse persistence-unit element.
         */
        private void startPersistenceUnit(Attributes attrs)
            throws SAXException {
            _excludeUnlistedSet = false;
            _info = new PersistenceUnitInfoImpl();
            _info.setPersistenceUnitName(attrs.getValue("name"));
            _info.setPersistenceXMLSchemaVersion(_persistenceVersion);

            // we only parse this ourselves outside a container, so default
            // transaction type to local
            String val = attrs.getValue("transaction-type");
            if (val == null)
                _info.setTransactionType(PersistenceUnitTransactionType.RESOURCE_LOCAL);
            else
                _info.setTransactionType(Enum.valueOf(PersistenceUnitTransactionType.class, val));

            if (_source != null)
                _info.setPersistenceXmlFileUrl(_source);
        }

        private void endPersistenceUnit() {
            if (!_excludeUnlistedSet) {
                setExcludeUnlistedClasses(null);
            }
        }

        private BigDecimal getPersistenceVersion() {
            if (_info.getPersistenceXMLSchemaVersion() != null) {
                try {
                    return new BigDecimal(_info.getPersistenceXMLSchemaVersion());
                }
                catch (Throwable t) {
                    log(_loc.get("invalid-version-attribute",
                        _info.getPersistenceXMLSchemaVersion(),
                        VERSION_1_0.toString()).toString());
                }
            }
            // OpenJPA supports persistence files without a version attribute.
            // A persistence file without a version attribute will be considered
            // a version 1.0 persistence file by default to maintain backward
            // compatibility.
            return VERSION_1_0;
        }
    }


    /**
     * This private class is used to hold onto information regarding
     * PersistentUnit name collisions.
     */
    private static class PUNameCollision{
        private String _puName;
        private Set<String> _resources;

        PUNameCollision(String puName, String file1, String file2) {
            _resources = new LinkedHashSet<>();
            _resources.add(file1);
            _resources.add(file2);

            _puName=puName;
        }

        void logCollision(Log logger){
            if(logger.isWarnEnabled()){
                logger.warn(_loc.getFatal("dup-pu", new Object[]{_puName,_resources.toString(),
                    _resources.iterator().next()}));
            }
        }

        void addCollision(String file1, String file2){
            _resources.add(file1);
            _resources.add(file2);
        }

    }
}
