/*
 * 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.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import java.util.HashMap;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.spi.ClassTransformer;
import javax.persistence.spi.LoadState;
import javax.persistence.spi.PersistenceProvider;
import javax.persistence.spi.PersistenceUnitInfo;
import javax.persistence.spi.ProviderUtil;

import org.apache.openjpa.conf.BrokerValue;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.conf.OpenJPAConfigurationImpl;
import org.apache.openjpa.enhance.PCClassFileTransformer;
import org.apache.openjpa.enhance.PCEnhancerAgent;
import org.apache.openjpa.kernel.Bootstrap;
import org.apache.openjpa.kernel.BrokerFactory;
import org.apache.openjpa.kernel.ConnectionRetainModes;
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.log.Log;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.MultiClassLoader;
import org.apache.openjpa.meta.AbstractCFMetaDataFactory;
import org.apache.openjpa.meta.MetaDataModes;
import org.apache.openjpa.meta.MetaDataRepository;
import org.apache.openjpa.persistence.osgi.BundleUtils;
import org.apache.openjpa.persistence.validation.ValidationUtils;
import org.apache.openjpa.util.ClassResolver;


/**
 * Bootstrapping class that allows the creation of a stand-alone
 * {@link EntityManager}.
 *
 * @see javax.persistence.Persistence#createEntityManagerFactory(String,Map)
 * @published
 */
public class PersistenceProviderImpl
    implements PersistenceProvider, ProviderUtil {

    static final String CLASS_TRANSFORMER_OPTIONS = "ClassTransformerOptions";
    private static final String EMF_POOL = "EntityManagerFactoryPool";

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

    private Log _log;
    /**
     * Loads the entity manager specified by <code>name</code>, applying
     * the properties in <code>m</code> as overrides to the properties defined
     * in the XML configuration file for <code>name</code>. If <code>name</code>
     * is <code>null</code>, this method loads the XML in the resource
     * identified by <code>resource</code>, and uses the first resource found
     * when doing this lookup, regardless of the name specified in the XML
     * resource or the name of the jar that the resource is contained in.
     * This does no pooling of EntityManagersFactories.
     * @return EntityManagerFactory or null
     */
    public OpenJPAEntityManagerFactory createEntityManagerFactory(String name, String resource, Map m) {
        PersistenceProductDerivation pd = new PersistenceProductDerivation();
        try {
            Object poolValue = Configurations.removeProperty(EMF_POOL, m);
            ConfigurationProvider cp = pd.load(resource, name, m);
            if (cp == null) {
                return null;
            }

            BrokerFactory factory = getBrokerFactory(cp, poolValue, BundleUtils.getBundleClassLoader());
            OpenJPAConfiguration conf = factory.getConfiguration();
            conf.setUserClassLoader(BundleUtils.getBundleClassLoader());
            _log = conf.getLog(OpenJPAConfiguration.LOG_RUNTIME);            
            pd.checkPuNameCollisions(_log,name);
            
            // add enhancer
            loadAgent(factory);
            
            // Create appropriate LifecycleEventManager
            loadValidator(factory);
            
            if (conf.getConnectionRetainModeConstant() == ConnectionRetainModes.CONN_RETAIN_ALWAYS) {
                // warn about EMs holding on to connections.
                _log.warn(_loc.get("retain-always", conf.getId()));
            }
            
            OpenJPAEntityManagerFactory emf = JPAFacadeHelper.toEntityManagerFactory(factory);
            if (_log.isTraceEnabled()) {
                _log.trace(this + " creating " + emf + " for PU " + name + ".");
            }
            return emf;
        } catch (Exception e) {
            if (_log != null) {
                _log.error(_loc.get("create-emf-error", name), e);
            }
            
            /*
             * 
             * Maintain 1.x behavior of throwing exceptions, even though
             * JPA2 9.2 - createEMF "must" return null for PU it can't handle.
             * 
             * JPA 2.0 Specification Section 9.2 states:
             * "If a provider does not qualify as the provider for the named persistence unit, 
             * it must return null when createEntityManagerFactory is invoked on it."
             * That specification compliance behavior has happened few lines above on null return. 
             * Throwing runtime exception in the following code is valid (and useful) behavior
             * because the qualified provider has encountered an unexpected situation.
             */
            throw PersistenceExceptions.toPersistenceException(e);                
        }
    }

    private BrokerFactory getBrokerFactory(ConfigurationProvider cp,
        Object poolValue, ClassLoader loader) {
        // handle "true" and "false"
        if (poolValue instanceof String
            && ("true".equalsIgnoreCase((String) poolValue)
                || "false".equalsIgnoreCase((String) poolValue)))
            poolValue = Boolean.valueOf((String) poolValue);

        if (poolValue != null && !(poolValue instanceof Boolean)) {
            // we only support boolean settings for this option currently.
            throw new IllegalArgumentException(poolValue.toString());
        }
        
        if (poolValue == null || !((Boolean) poolValue).booleanValue())
            return Bootstrap.newBrokerFactory(cp, loader);
        else
            return Bootstrap.getBrokerFactory(cp, loader);
    }

    public OpenJPAEntityManagerFactory createEntityManagerFactory(String name, Map m) {
        return createEntityManagerFactory(name, null, m);
    }

    public OpenJPAEntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo pui, Map m) {
        PersistenceProductDerivation pd = new PersistenceProductDerivation();
        try {
            Object poolValue = Configurations.removeProperty(EMF_POOL, m);
            ConfigurationProvider cp = pd.load(pui, m);
            if (cp == null)
                return null;

            // add enhancer
            Exception transformerException = null;
            String ctOpts = (String) Configurations.getProperty(CLASS_TRANSFORMER_OPTIONS, pui.getProperties());
            try {
                pui.addTransformer(new ClassTransformerImpl(cp, ctOpts,
                    pui.getNewTempClassLoader(), newConfigurationImpl()));
            } catch (Exception e) {
                // fail gracefully
                transformerException = e;
            }

            // if the BrokerImpl hasn't been specified, switch to the
            // non-finalizing one, since anything claiming to be a container
            // should be doing proper resource management.
            if (!Configurations.containsProperty(BrokerValue.KEY, cp.getProperties())) {
                cp.addProperty("openjpa." + BrokerValue.KEY, getDefaultBrokerAlias());
            }


            ClassLoader loader = pui.getClassLoader();
            if (BundleUtils.runningUnderOSGi()) {
                // OPENJPA-1491 : If running under OSGi, use the Bundle's ClassLoader instead of the application one
                // OPENJPA-2542 : Also try to load from app loader in the case of a user implemented interface/config 
                loader = new MultiClassLoader(BundleUtils.getBundleClassLoader(), loader);
            }
            BrokerFactory factory = getBrokerFactory(cp, poolValue, loader);
            OpenJPAConfiguration conf = factory.getConfiguration();
            setPersistenceEnvironmentInfo(conf, pui);
            _log = conf.getLog(OpenJPAConfiguration.LOG_RUNTIME);
            // now we can log any transformer exceptions from above
            if (transformerException != null) {
                if (_log.isTraceEnabled()) {
                    _log.warn(_loc.get("transformer-registration-error-ex", pui), transformerException);
                } else {
                    _log.warn(_loc.get("transformer-registration-error", pui));
                }
            }
            
            if (conf.getConnectionRetainModeConstant() == ConnectionRetainModes.CONN_RETAIN_ALWAYS) {
                // warn about container managed EMs holding on to connections.
                _log.warn(_loc.get("cm-retain-always",conf.getId()));
            }

            // Create appropriate LifecycleEventManager
            loadValidator(factory);
            
            OpenJPAEntityManagerFactory emf = JPAFacadeHelper.toEntityManagerFactory(factory);
            if (_log.isTraceEnabled()) {
                _log.trace(this + " creating container " + emf + " for PU " + pui.getPersistenceUnitName() + ".");
            }
            
            return emf;
        } catch (Exception e) {
            throw PersistenceExceptions.toPersistenceException(e);
        }
    }

    @Override
    public void generateSchema(PersistenceUnitInfo info, Map map) {
        throw new UnsupportedOperationException("JPA 2.1");
    }

    @Override
    public boolean generateSchema(String persistenceUnitName, Map map) {
        throw new UnsupportedOperationException("JPA 2.1");
    }

    public void setPersistenceEnvironmentInfo(OpenJPAConfiguration conf, PersistenceUnitInfo pui) {
        // OPENJPA-1460 Fix scope visibility of orm.xml when it is packaged in both ear file and war file
        if (conf instanceof OpenJPAConfigurationImpl) {
            Map<String, Object> peMap =((OpenJPAConfigurationImpl)conf).getPersistenceEnvironment();
            if (peMap == null) {
                peMap = new HashMap<String, Object>();
                ((OpenJPAConfigurationImpl)conf).setPersistenceEnvironment(peMap);
            }
            peMap.put(AbstractCFMetaDataFactory.PERSISTENCE_UNIT_ROOT_URL, pui.getPersistenceUnitRootUrl());
            peMap.put(AbstractCFMetaDataFactory.MAPPING_FILE_NAMES, pui.getMappingFileNames());
            peMap.put(AbstractCFMetaDataFactory.JAR_FILE_URLS, pui.getJarFileUrls());
        }
    }
    
    /*
     * Returns a ProviderUtil for use with entities managed by this
     * persistence provider.
     */
    public ProviderUtil getProviderUtil() {
        return this;
    }

    /*
     * Returns a default Broker alias to be used when no openjpa.BrokerImpl
     *  is specified. This method allows PersistenceProvider subclass to
     *  override the default broker alias.
     */
    protected String getDefaultBrokerAlias() {
        return BrokerValue.NON_FINALIZING_ALIAS;
    }
    
    /*
     * Return a new instance of Configuration subclass used by entity
     * enhancement in ClassTransformerImpl. If OpenJPAConfigurationImpl
     * instance is used, configuration options declared in configuration
     * sub-class will not be recognized and a warning is posted in the log.
     */
    protected OpenJPAConfiguration newConfigurationImpl() {
        return new OpenJPAConfigurationImpl();
    }
   
    /**
     * Java EE 5 class transformer.
     */
    private static class ClassTransformerImpl
        implements ClassTransformer {

        private final ClassFileTransformer _trans;

        private ClassTransformerImpl(ConfigurationProvider cp, String props, 
            final ClassLoader tmpLoader, OpenJPAConfiguration conf) {
            cp.setInto(conf);
            // use the temporary loader for everything
            conf.setClassResolver(new ClassResolver() {
                public ClassLoader getClassLoader(Class<?> context, ClassLoader env) {
                    return tmpLoader;
                }
            });
            conf.setReadOnly(Configuration.INIT_STATE_FREEZING);

            MetaDataRepository repos = conf.getMetaDataRepositoryInstance();
            repos.setResolve(MetaDataModes.MODE_MAPPING, false);
            _trans = new PCClassFileTransformer(repos,
                Configurations.parseProperties(props), tmpLoader);
        }

        public byte[] transform(ClassLoader cl, String name,
            Class<?> previousVersion, ProtectionDomain pd, byte[] bytes)
            throws IllegalClassFormatException {
            return _trans.transform(cl, name, previousVersion, pd, bytes);
        }
	}
    
    /**
     * This private worker method will attempt load the PCEnhancerAgent.
     */
    private void loadAgent(BrokerFactory factory) {
        OpenJPAConfiguration conf = factory.getConfiguration();
        Log log = conf.getLog(OpenJPAConfiguration.LOG_RUNTIME);

        if (conf.getDynamicEnhancementAgent() == true) {
            boolean res = PCEnhancerAgent.loadDynamicAgent(log);
            if (log.isInfoEnabled() && res == true ){
                log.info(_loc.get("dynamic-agent"));
            }
        }
    }
    
    /**
     * This private worker method will attempt to setup the proper
     * LifecycleEventManager type based on if the javax.validation APIs are
     * available and a ValidatorImpl is required by the configuration.
     * @param log
     * @param conf
     * @throws if validation setup failed and was required by the config
     */
    private void loadValidator(BrokerFactory factory) {
        OpenJPAConfiguration conf = factory.getConfiguration();
        Log log = conf.getLog(OpenJPAConfiguration.LOG_RUNTIME);

        if ((ValidationUtils.setupValidation(conf) == true) &&
                log.isInfoEnabled()) {
            log.info(_loc.get("vlem-creation-info"));
        }
    }

    /**
     * Determines whether the specified object is loaded.
     * 
     * @return LoadState.LOADED - if all implicit or explicit EAGER fetch
     *         attributes are loaded
     *         LoadState.NOT_LOADED - if any implicit or explicit EAGER fetch
     *         attribute is not loaded
     *         LoadState.UNKNOWN - if the entity is not managed by this
     *         provider.
     */
    public LoadState isLoaded(Object obj) {
        return isLoadedWithoutReference(obj, null);
    }

    /**
     * Determines whether the attribute on the specified object is loaded.  This
     * method may access the value of the attribute to determine load state (but
     * currently does not).
     * 
     * @return LoadState.LOADED - if the attribute is loaded.
     *         LoadState.NOT_LOADED - if the attribute is not loaded or any
     *         EAGER fetch attributes of the entity are not loaded.
     *         LoadState.UNKNOWN - if the entity is not managed by this
     *         provider or if it does not contain the persistent
     *         attribute.
     */
    public LoadState isLoadedWithReference(Object obj, String attr) {
        // TODO: Are there be any cases where OpenJPA will need to examine
        // the contents of a field to determine load state?  If so, per JPA 
        // contract, this method permits that sort of access. In the extremely 
        // unlikely case that the the entity is managed by multiple providers, 
        // even if it doesn't trigger loading in OpenJPA, accessing field data 
        // could trigger loading by an alternate provider.
        return isLoadedWithoutReference(obj, attr);
    }

    /**
     * Determines whether the attribute on the specified object is loaded.  This
     * method does not access the value of the attribute to determine load 
     * state.
     * 
     * @return LoadState.LOADED - if the attribute is loaded.
     *         LoadState.NOT_LOADED - if the attribute is not loaded or any
     *         EAGER fetch attributes of the entity are not loaded.
     *         LoadState.UNKNOWN - if the entity is not managed by this
     *         provider or if it does not contain the persistent
     *         attribute.
     */
    public LoadState isLoadedWithoutReference(Object obj, String attr) {        
        if (obj == null) {
            return LoadState.UNKNOWN;
        }

        return OpenJPAPersistenceUtil.isLoaded(obj, attr);
    }
}
