/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 * 
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License. You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [year]
 * [name of copyright owner]"
 * 
 * Contributor(s):
 * 
 * Mike Keith - Add ability to run in OSGi and other environments by making 
 *              provider discovery a strategy. Also allow providers to be added
 *              and removed dynamically.
 *               
 * Mike Keith elects to include this software in this distribution under 
 * the CDDL license.
 * 
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
package javax.persistence;

// J2SE imports
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import java.util.Map;
import java.util.HashSet;
import java.util.Enumeration;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

// persistence imports
import javax.persistence.spi.PersistenceProvider;

/**
 * Bootstrap class that is used to obtain an {@link EntityManagerFactory}.
 *
 * @since Java Persistence 1.0
 */
public class Persistence {

    protected static Set<PersistenceProvider> providers = new HashSet<PersistenceProvider>();

    // Used to resolve and return providers.
    protected static ProviderResolver providerResolver = new DefaultProviderResolver();
    
    /**
     * Get the resolver being used to obtain the available providers. 
     * 
     * @return The resolver used to obtain all available providers
     */
    public static ProviderResolver getProviderResolver() { return providerResolver; }

    /**
     * Set the resolver to an alternate provider resolution strategy (implemented externally).
     * This can be used to override the default resolution strategy.
     * 
     * @param resolver The resolver to use when obtaining all available providers
     */
    public static void setProviderResolver(ProviderResolver resolver) { providerResolver = resolver; }
    
    /**
     * 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, null);
    }

    /**
     * Create and return an EntityManagerFactory for the 
     * named persistence unit using the given properties.
     * 
     * @param persistenceUnitName The name of the persistence unit
     * @param properties Additional properties to use when creating the 
     * factory. The values of these properties override any values
     * that may have been configured elsewhere.
     * @return The factory that creates EntityManagers configured 
     * according to the specified persistence unit.
     */
    public static EntityManagerFactory createEntityManagerFactory(
            String persistenceUnitName, Map properties) {

    	EntityManagerFactory emf = null;
        if (providers.size() == 0) {
            try{
                providers.addAll(providerResolver.findAllProviders());
            } catch (IOException exc){}
        }
        for (PersistenceProvider provider : providers) {
            emf = provider.createEntityManagerFactory(persistenceUnitName, properties);
            if (emf != null){
                break;
            }
        }
        if (emf == null) {
            throw new PersistenceException("No Persistence provider for EntityManager named " + persistenceUnitName);
        }
        return emf;
    }

    // ====================
    // Internal API methods
    // ====================
    
    /**
     * Dynamically add a provider to the set of available providers.
     */
    public static void addProvider(PersistenceProvider provider) {
    	providers.add(provider);
    }

    /**
     * Dynamically remove a named provider from the set of available providers.
     */
    public static void removeProvider(String providerName) {
        for (Iterator<PersistenceProvider> i = providers.iterator(); i.hasNext(); ) {
    		if (i.next().getClass().getName().equals(providerName)) { 
    			i.remove();
    		}
		}
    }

    /**
     * Reinitialize to have no providers.
     */
    public static void resetProviders() {
    	providers = new HashSet<PersistenceProvider>();
    }

    // ==============================================================
    // Interface for overriding available provider discovery strategy
    // ==============================================================

    /**
     * Interface used by the Persistence class to obtain all available persistence providers.
     */
    public static interface ProviderResolver {
    	Collection<PersistenceProvider> findAllProviders() throws IOException;
    }

    // =============================
    // Internal implementation class 
    // =============================
    
    /**
     * Default provider resolver class to use when none is explicitly set.
     * 
     * Uses the META-INF/services approach as described in the Java Persistence 
     * specification. A getResources() call is made on the current context classloader 
     * to find the service provider files on the classpath. Any service files found
     * are then read to obtain the classes that implement the persistence provider 
     * interface.
     */
    public static class DefaultProviderResolver implements ProviderResolver {
    	
        public static final String PERSISTENCE_PROVIDER = "javax.persistence.spi.PersistenceProvider";
    	public static final String SERVICE_PROVIDER_FILE = "META-INF/services/" + PERSISTENCE_PROVIDER;


    	public Collection<PersistenceProvider> findAllProviders() throws IOException {
    	
	        ClassLoader loader = Thread.currentThread().getContextClassLoader();
	        Enumeration<URL> resources = loader.getResources(SERVICE_PROVIDER_FILE);
	
	        Set<String> providerNames = new HashSet<String>();
	        while (resources.hasMoreElements()) {
	            URL url = resources.nextElement();
	            InputStream is = url.openStream();
	            try {
	            	providerNames.addAll(providerNamesFromReader(new BufferedReader(new InputStreamReader(is))));
	            } finally {
	                is.close();
	            }
	        }
	        Collection<PersistenceProvider> loadedProviders = new HashSet<PersistenceProvider>();  
	        for (String s : providerNames) {
	            try{
	            	loadedProviders.add((PersistenceProvider)loader.loadClass(s).newInstance());
	            } catch (ClassNotFoundException exc){
	            } catch (InstantiationException exc){
	            } catch (IllegalAccessException exc){
	            }
	        }
	        return loadedProviders;
    	}

    	private static final Pattern nonCommentPattern = Pattern.compile("^([^#]+)");

	    private Set<String> providerNamesFromReader(BufferedReader reader) throws IOException {
	        Set<String> providerNames = new HashSet<String>();
	        String line;
	        while ((line = reader.readLine()) != null) {
	            line = line.trim();
	            Matcher m = nonCommentPattern.matcher(line);
	            if (m.find()) {
	            	providerNames.add(m.group().trim());
	            }
	        }
	        return providerNames;
	    }
    }
}
