/*
 * 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.
 */

//
// This source code implements specifications defined by the Java
// Community Process. In order to remain compliant with the specification
// DO NOT add / change / or delete method signatures!
//
package javax.persistence;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.persistence.spi.PersistenceProvider;

/**
 * @version $Rev$ $Date$
 */

/**
 * Bootstrap class that is used to obtain {@link javax.persistence.EntityManagerFactory}
 * references.
 */
public class Persistence {
    
    protected static final Set<PersistenceProvider> providers = new HashSet<PersistenceProvider>();
    // Changed to the hard coded PERSISTENCE_PROVIDER value to pass signature tests.
    // public static final java.lang.String PERSISTENCE_PROVIDER = PersistenceProvider.class.getName();
    public static final java.lang.String PERSISTENCE_PROVIDER = "javax.persistence.spi.PersistenceProvider";
    static final String PERSISTENCE_PROVIDER_PROPERTY = "javax.persistence.provider";
    static final String PERSISTENCE_PROVIDER_SERVICE = "META-INF/services/"
        + PersistenceProvider.class.getName();
    
    /**
     * Create and return an EntityManagerFactory for the named persistence unit.
     * 
     * @param persistenceUnitName The name of the persistence unit
     * @return The factory that creates EntityManagers configured according to the specified persistence unit
     */
    public static EntityManagerFactory createEntityManagerFactory(String persistenceUnitName) {
        return createEntityManagerFactory(persistenceUnitName, Collections.EMPTY_MAP);
    }
    
    public static EntityManagerFactory createEntityManagerFactory(String persistenceUnitName, Map properties) {
        
        if (properties == null) {
            properties = Collections.EMPTY_MAP;
        }
        
        // start by loading a provider explicitly specified in properties. The spec
        // doesn't seem to forbid providers that are not deployed as a service
        Object providerName = properties.get(PERSISTENCE_PROVIDER_PROPERTY);
        if (providerName instanceof String) {
            EntityManagerFactory factory = createFactory(providerName.toString(), persistenceUnitName, properties);
            if (factory != null) {
                return factory;
            }
        }
        
        // If we are deployed into an OSGi environment, leverage it
        Class<? extends PersistenceProvider> providerClass = org.apache.servicemix.specs.locator.OsgiLocator.locate(PersistenceProvider.class);
        if (providerClass != null) {
            try {
                PersistenceProvider provider = providerClass.newInstance();
                return provider.createEntityManagerFactory(persistenceUnitName, properties);
            }
            catch (Exception e) {
                throw new PersistenceException("Provider error. Provider: " + providerName, e);
            }
        }
        
        // load correctly deployed providers
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        try {
            Enumeration<URL> providers = loader.getResources(PERSISTENCE_PROVIDER_SERVICE);
            while (providers.hasMoreElements()) {
                
                String name = getProviderName(providers.nextElement());
                
                if (name != null) {
                    
                    EntityManagerFactory factory = createFactory(name, persistenceUnitName, properties);
                    
                    if (factory != null) {
                        return factory;
                    }
                }
            }
        }
        catch (IOException e) {
            // spec doesn't mention any exceptions thrown by this method
        }
        
        return null;
    }
    
    static String getProviderName(URL url) throws IOException {
        
        BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));
        
        String providerName;
        
        try {
            providerName = in.readLine();
        }
        finally {
            in.close();
        }
        
        if (providerName != null) {
            providerName = providerName.trim();
        }
        
        return providerName;
    }
    
    static EntityManagerFactory createFactory(String providerName, String persistenceUnitName, Map properties) throws PersistenceException {
        
        Class providerClass;
        try {
            providerClass = Class.forName(providerName, true, Thread.currentThread().getContextClassLoader());
        }
        catch (Exception e) {
            throw new PersistenceException("Invalid or inaccessible provider class: " + providerName, e);
        }
        
        try {
            PersistenceProvider provider = (PersistenceProvider) providerClass.newInstance();
            return provider.createEntityManagerFactory(persistenceUnitName, properties);
        }
        catch (Exception e) {
            throw new PersistenceException("Provider error. Provider: " + providerName, e);
        }
        
    }

}
