/*
 * 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.lang.reflect.Method;
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.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.persistence.SharedCacheMode;
import javax.persistence.ValidationMode;
import javax.persistence.spi.ClassTransformer;
import javax.persistence.spi.PersistenceUnitInfo;
import javax.persistence.spi.PersistenceUnitTransactionType;
import javax.sql.DataSource;

import org.apache.openjpa.lib.conf.Configuration;
import org.apache.openjpa.lib.conf.Configurations;
import org.apache.openjpa.lib.conf.ProductDerivations;
import org.apache.openjpa.lib.meta.SourceTracker;
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.util.ClassResolver;

/**
 * Implementation of the {@link PersistenceUnitInfo} interface used by OpenJPA
 * when parsing persistence configuration information.
 *
 */
public class PersistenceUnitInfoImpl
    implements PersistenceUnitInfo, SourceTracker {

    public static final String PERSISTENCE_VERSION = "PersistenceVersion";


    private static final Localizer s_loc = Localizer.forPackage
        (PersistenceUnitInfoImpl.class);

    private String _name;
    private final HashMap<Object,Object> _props = new HashMap<>();
    private PersistenceUnitTransactionType _transType =
        PersistenceUnitTransactionType.RESOURCE_LOCAL;

    private String _providerClassName;
    private List<String> _mappingFileNames;
    private List<String> _entityClassNames;
    private List<URL> _jarFiles;
    private List<String> _jarFileNames;
    private String _jtaDataSourceName;
    private DataSource _jtaDataSource;
    private String _nonJtaDataSourceName;
    private DataSource _nonJtaDataSource;
    private boolean _excludeUnlisted;
    private URL _persistenceXmlFile;
    private String _schemaVersion = "1.0";
    private ValidationMode _validationMode;
    private SharedCacheMode _sharedCacheMode;

    // A persistence unit is defined by a persistence.xml file. The jar
    // file or directory whose META-INF directory contains the
    // persistence.xml file is termed the root of the persistence unit.
    //
    // In Java EE, the root of a persistence unit may be one of the following:
    // - an EJB-JAR file
    // - the WEB-INF/classes directory of a WAR file[38]
    // - a jar file in the WEB-INF/lib directory of a WAR file
    // - a jar file in the root of the EAR
    // - a jar file in the EAR library directory
    // - an application client jar file
    private URL _root;

    @Override
    public ClassLoader getClassLoader() {
        return null;
    }

    @Override
    public ClassLoader getNewTempClassLoader() {
        return AccessController.doPrivileged(J2DoPrivHelper
            .newTemporaryClassLoaderAction(AccessController
                .doPrivileged(J2DoPrivHelper.getContextClassLoaderAction())));
    }

    @Override
    public String getPersistenceUnitName() {
        return _name;
    }

    public void setPersistenceUnitName(String emName) {
        _name = emName;
    }

    @Override
    public String getPersistenceProviderClassName() {
        return _providerClassName;
    }

    public void setPersistenceProviderClassName(String providerClassName) {
        _providerClassName = providerClassName;
    }

    @Override
    public PersistenceUnitTransactionType getTransactionType() {
        return _transType;
    }

    public void setTransactionType(PersistenceUnitTransactionType transType) {
        _transType = transType;
    }

    public String getJtaDataSourceName() {
        return _jtaDataSourceName;
    }

    public void setJtaDataSourceName(String jta) {
        _jtaDataSourceName = jta;
        if (jta != null)
            _jtaDataSource = null;
    }

    @Override
    public DataSource getJtaDataSource() {
        return _jtaDataSource;
    }

    public void setJtaDataSource(DataSource ds) {
        _jtaDataSource = ds;
        if (ds != null)
            _jtaDataSourceName = null;
    }

    public String getNonJtaDataSourceName() {
        return _nonJtaDataSourceName;
    }

    public void setNonJtaDataSourceName(String nonJta) {
        _nonJtaDataSourceName = nonJta;
        if (nonJta != null)
            _nonJtaDataSource = null;
    }

    @Override
    public DataSource getNonJtaDataSource() {
        return _nonJtaDataSource;
    }

    public void setNonJtaDataSource(DataSource ds) {
        _nonJtaDataSource = ds;
        if (ds != null)
            _nonJtaDataSourceName = null;
    }

    @Override
    public URL getPersistenceUnitRootUrl() {
        return _root;
    }

    public void setPersistenceUnitRootUrl(URL root) {
        _root = root;
    }

    @Override
    public boolean excludeUnlistedClasses() {
        return _excludeUnlisted;
    }

    public void setExcludeUnlistedClasses(boolean excludeUnlisted) {
        _excludeUnlisted = excludeUnlisted;
    }

    @Override
    public List<String> getMappingFileNames() {
        if (_mappingFileNames == null)
            return Collections.emptyList();
        return _mappingFileNames;
    }

    public void addMappingFileName(String name) {
        if (_mappingFileNames == null)
            _mappingFileNames = new ArrayList<>();
        _mappingFileNames.add(name);
    }

    @Override
    public List<URL> getJarFileUrls() {
        if (_jarFiles == null)
            return Collections.emptyList();
        return _jarFiles;
    }

    public void addJarFile(URL jar) {
        if (_jarFiles == null)
            _jarFiles = new ArrayList<>();
        _jarFiles.add(jar);
    }

    public void addJarFileName(String name) {
        // Defer searching the classpath for jar files referenced by the jar-file element until after
        // the XML has been parsed and it has been confirmed that OpenJPA is the desired JPA provider.

        if (_jarFileNames == null) {
            _jarFileNames = new ArrayList<>();
        }
        _jarFileNames.add(name);
    }

    /**
     * Process jar-file elements. An IllegalArgumentException may be thrown if the jar file does not exist in the
     * classpath.
     */
    public void processJarFileNames() {
        if (_jarFileNames != null) {
            for (String name : _jarFileNames) {
                validateJarFileName(name);
            }

            _jarFileNames.clear();
        }
    }

    public void validateJarFileName(String name) {
        ClassLoader contextClassLoader = AccessController.doPrivileged(J2DoPrivHelper.getContextClassLoaderAction());
        MultiClassLoader loader = AccessController
            .doPrivileged(J2DoPrivHelper.newMultiClassLoaderAction());
        loader.addClassLoader(contextClassLoader);
        loader.addClassLoader(getClass().getClassLoader());
        loader.addClassLoader(MultiClassLoader.THREAD_LOADER);
        URL url = AccessController.doPrivileged(
            J2DoPrivHelper.getResourceAction(loader, name));
        if (url != null) {
            addJarFile(url);
            return;
        }

        // jar file is not a resource; check classpath
        String classPath = null;

        //first check if the classpath is set from ant class loader
        if (contextClassLoader instanceof MultiClassLoader) {
            for (ClassLoader classLoader : ((MultiClassLoader) contextClassLoader).getClassLoaders()){
                try {
                    Method getClassPathMethod = classLoader.getClass().getMethod("getClasspath", new Class[]{});
                    classPath = (String) getClassPathMethod.invoke(classLoader, new Object[]{});
                    if (classPath != null)
                        break;
                } catch (Exception e) {
                    //do nothing
                }
            }
        }

        if (classPath == null) {
            classPath = AccessController.doPrivileged(
                    J2DoPrivHelper.getPropertyAction("java.class.path"));
        }
        String[] cp = classPath.split(J2DoPrivHelper.getPathSeparator());

        for (String s : cp) {
            if (s.equals(name)
                    || s.endsWith(File.separatorChar + name)) {
                try {
                    addJarFile(AccessController
                            .doPrivileged(J2DoPrivHelper
                                    .toURLAction(new File(s))));
                    return;
                }
                catch (PrivilegedActionException | MalformedURLException pae) {
                    break;
                }
            }
        }
        throw new IllegalArgumentException(s_loc.get("bad-jar-name", name).
            getMessage());
    }

    @Override
    public List<String> getManagedClassNames() {
        if (_entityClassNames == null)
            return Collections.emptyList();
        return _entityClassNames;
    }

    public void addManagedClassName(String name) {
        if (_entityClassNames == null)
            _entityClassNames = new ArrayList<>();
        _entityClassNames.add(name);
    }

    @Override
    public Properties getProperties() {
        Properties copy = new Properties();
        copy.putAll(_props);
        return copy;
    }

    public void setProperty(String key, String value) {
        _props.put(key, value);
    }

    @Override
    public void addTransformer(ClassTransformer transformer) {
        throw new UnsupportedOperationException();
    }

    /**
     * The location of the persistence.xml resource. May be null.
     */
    public URL getPersistenceXmlFileUrl() {
        return _persistenceXmlFile;
    }

    /**
     * The location of the persistence.xml resource. May be null.
     */
    public void setPersistenceXmlFileUrl(URL url) {
        _persistenceXmlFile = url;
    }

    /**
     * Load the given user-supplied map of properties into this persistence
     * unit.
     */
    public void fromUserProperties(Map map) {
        if (map == null)
            return;

        Object key;
        Object val;
        for (Object o : map.entrySet()) {
            key = ((Map.Entry) o).getKey();
            val = ((Map.Entry) o).getValue();
            if (JPAProperties.PROVIDER.equals(key))
                setPersistenceProviderClassName((String) val);
            else if (JPAProperties.TRANSACTION_TYPE.equals(key)) {
                setTransactionType(JPAProperties.getEnumValue(PersistenceUnitTransactionType.class, val));
            } else if (JPAProperties.DATASOURCE_JTA.equals(key)) {
                if (val instanceof String) {
                    setJtaDataSourceName((String) val);
                } else {
                    setJtaDataSource((DataSource) val);
                }
            } else if (JPAProperties.DATASOURCE_NONJTA.equals(key)) {
                if (val instanceof String) {
                    setNonJtaDataSourceName((String) val);
                } else {
                    setNonJtaDataSource((DataSource) val);
                }
            } else if (JPAProperties.VALIDATE_MODE.equals(key)) {
                setValidationMode(JPAProperties.getEnumValue(ValidationMode.class, val));
            } else if (JPAProperties.CACHE_MODE.equals(key)) {
                setSharedCacheMode(JPAProperties.getEnumValue(SharedCacheMode.class, val));
            } else {
                _props.put(key, val);
            }
        }
    }

    /**
     * Return a {@link Map} containing the properties necessary to create
     * a {@link Configuration} that reflects the information in this
     * persistence unit info.
     */
    public Map toOpenJPAProperties() {
        return toOpenJPAProperties(this);
    }

    /**
     * Return a {@link Map} containing the properties necessary to create
     * a {@link Configuration} that reflects the information in the given
     * persistence unit info.
     */
    public static Map toOpenJPAProperties(PersistenceUnitInfo info) {
        Map map = new HashMap<String,Object>();
        Set<String> added = new HashSet<>();
        if (info.getTransactionType() == PersistenceUnitTransactionType.JTA)
            replaceAsOpenJPAProperty(map, added, "TransactionMode", "managed");

        boolean hasJta = false;
        DataSource ds = info.getJtaDataSource();
        if (ds != null) {
            replaceAsOpenJPAProperty(map, added, "ConnectionFactory", ds);
            replaceAsOpenJPAProperty(map, added, "ConnectionFactoryMode", "managed");
            hasJta = true;
        } else if (info instanceof PersistenceUnitInfoImpl
            && ((PersistenceUnitInfoImpl) info).getJtaDataSourceName() != null){
            replaceAsOpenJPAProperty(map, added, "ConnectionFactoryName",
                    ((PersistenceUnitInfoImpl)info).getJtaDataSourceName());
            replaceAsOpenJPAProperty(map, added, "ConnectionFactoryMode", "managed");
            hasJta = true;
        }

        ds = info.getNonJtaDataSource();
        if (ds != null) {
             replaceAsOpenJPAProperty(map, added, hasJta ? "ConnectionFactory2" : "ConnectionFactory", ds);
        } else if (info instanceof PersistenceUnitInfoImpl
            && ((PersistenceUnitInfoImpl) info).getNonJtaDataSourceName() != null) {
            String nonJtaName = ((PersistenceUnitInfoImpl) info).getNonJtaDataSourceName();
            replaceAsOpenJPAProperty(map, added, hasJta ? "ConnectionFactory2Name" : "ConnectionFactoryName",
                    nonJtaName);
        }

        if (info.getClassLoader() != null)
            replaceAsOpenJPAProperty(map, added, "ClassResolver", new ClassResolverImpl(info.getClassLoader()));

        Properties props = info.getProperties();
        if (props != null) {
            // remove any of the things that were set above
            for (String key : added) {
                if (Configurations.containsProperty(key, props))
                    Configurations.removeProperty(key, props);
            }

            // add all the non-conflicting props in the <properties> section
            map.putAll(props);

            // this isn't a real config property; remove it
            map.remove(PersistenceProviderImpl.CLASS_TRANSFORMER_OPTIONS);
        }

        if (!Configurations.containsProperty("Id", map))
            map.put("openjpa.Id", info.getPersistenceUnitName());

        Properties metaFactoryProps = new Properties();
        if (info.getManagedClassNames() != null
            && !info.getManagedClassNames().isEmpty()) {
            StringBuilder types = new StringBuilder();
            for (String type : info.getManagedClassNames()) {
                if (types.length() > 0)
                    types.append(';');
                types.append(type);
            }
            metaFactoryProps.put("Types", types.toString());
        }
        if (info.getJarFileUrls() != null && !info.getJarFileUrls().isEmpty()
            || (!info.excludeUnlistedClasses()
            && info.getPersistenceUnitRootUrl() != null)) {
            StringBuilder jars = new StringBuilder();
            String file = null;
            if (!info.excludeUnlistedClasses()
                && info.getPersistenceUnitRootUrl() != null) {
                URL url = info.getPersistenceUnitRootUrl();
                if ("file".equals(url.getProtocol())) // exploded jar?
                    file = URLDecoder.decode(url.getPath());
                else
                    jars.append(url);
            }
            for (URL jar : info.getJarFileUrls()) {
                if (jars.length() > 0)
                    jars.append(';');
                jars.append(jar);
            }
            if (file != null)
                metaFactoryProps.put("Files", file);
            if (jars.length() != 0)
                metaFactoryProps.put("URLs", jars.toString());
        }
        if (info.getMappingFileNames() != null
            && !info.getMappingFileNames().isEmpty()) {
            StringBuilder rsrcs = new StringBuilder();
            for (String rsrc : info.getMappingFileNames()) {
                if (rsrcs.length() > 0)
                    rsrcs.append(';');
                rsrcs.append(rsrc);
            }
            metaFactoryProps.put("Resources", rsrcs.toString());
        }

        // set persistent class locations as properties of metadata factory,
        // combining them with any existing metadata factory props
        if (!metaFactoryProps.isEmpty()) {
            String key = ProductDerivations.getConfigurationKey
                ("MetaDataFactory", map);
            map.put(key, Configurations.combinePlugins((String) map.get(key),
                Configurations.serializeProperties(metaFactoryProps)));
        }

        // always record provider name for product derivations to access
        if (info.getPersistenceProviderClassName() != null)
            map.put(JPAProperties.PROVIDER, info.getPersistenceProviderClassName());

        // convert validation-mode enum to a StringValue
        if (info.getValidationMode() != null)
            map.put(JPAProperties.VALIDATE_MODE, info.getValidationMode());

        if (info.getPersistenceXMLSchemaVersion() != null) {
            map.put(PERSISTENCE_VERSION, info.getPersistenceXMLSchemaVersion());
        }

        if (info.getSharedCacheMode() != null) {
            map.put(JPAProperties.CACHE_MODE, info.getSharedCacheMode());
        }

        return map;
    }

    /**
     * Adds the given key-val to the given map after adding "openjpa." prefix to the key.
     * Tracks this addition in the given set of added keys.
     */
    private static void replaceAsOpenJPAProperty(Map map, Set<String> added, String key, Object val) {
        map.put("openjpa." + key, val);
        added.add(key);
    }

    // --------------------

    @Override
    public File getSourceFile() {
        if (_persistenceXmlFile == null)
            return null;

        try {
            return new File(_persistenceXmlFile.toURI());
        } catch (URISyntaxException e) {
            throw new IllegalStateException(e);
        }
    }

    @Override
    public Object getSourceScope() {
        return null;
    }

    @Override
    public int getSourceType() {
        return SRC_XML;
    }

    @Override
    public int getLineNumber() {
        return 0;
    }

    @Override
    public int getColNumber() {
        return 0;
    }

    @Override
    public String getResourceName() {
        return "PersistenceUnitInfo:" + _name;
    }

    /**
     * Simple class resolver built around the persistence unit loader.
     */
    public static class ClassResolverImpl
        implements ClassResolver {

        private final ClassLoader _loader;

        public ClassResolverImpl(ClassLoader loader) {
            _loader = loader;
        }

        @Override
        public ClassLoader getClassLoader(Class ctx, ClassLoader env) {
            return _loader;
        }
	}

    @Override
    public String getPersistenceXMLSchemaVersion() {
        return _schemaVersion;
    }

    public void setPersistenceXMLSchemaVersion(String version) {
        _schemaVersion = version;
    }

    @Override
    public ValidationMode getValidationMode() {
        return _validationMode;
    }

    public void setValidationMode(ValidationMode mode) {
        _validationMode = mode;
    }

    @Override
    public SharedCacheMode getSharedCacheMode() {
        return _sharedCacheMode;
    }

    public void setSharedCacheMode(SharedCacheMode mode) {
        _sharedCacheMode = mode;
    }
}
