/*
 * 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.lib.util.StringUtil;
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.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<String,PUNameCollision>();
    
    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<String>();
    
    // 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();
	}
    
    public void putBrokerFactoryAliases(Map<String, String> m) {
    }

    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.booleanValue()) ? 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<String>();
        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<PersistenceUnitInfoImpl>();
        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_1_0 = "persistence_1_0.xsd";
        private static final String PERSISTENCE_XSD_2_0 = "persistence_2_0.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 (_persistenceVersion != null && _persistenceVersion.equals(XMLVersionParser.VERSION_2_0) 
            || (_schemaLocation != null && _schemaLocation.indexOf(PERSISTENCE_XSD_2_0) != -1)) {
                persistencexsd = "persistence_2_0-xsd.rsrc";
            }
            return getClass().getResourceAsStream(persistencexsd);
        }

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

        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;
        }

        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<String>();
            _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);
        }

    }
}
