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

// $Id: FactoryFinder.java 670432 2008-06-23 02:02:08Z mrglavas $

package javax.xml.datatype;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Properties;

/**
 * <p>Implement pluggabile Datatypes.</p>
 * 
 * <p>This class is duplicated for each JAXP subpackage so keep it in
 * sync.  It is package private for secure class loading.</p>
 *
 * @author <a href="mailto:Jeff.Suttor@Sun.com">Jeff Suttor</a>
 * @version $Revision: 670432 $, $Date: 2008-06-22 19:02:08 -0700 (Sun, 22 Jun 2008) $
 * @since 1.5
 */
final class FactoryFinder {
	
	/**
	 * <p>Name of class to display in output messages.</p>
	 */
	private static final String CLASS_NAME = "javax.xml.datatype.FactoryFinder";
	
    /**
     * <p>Debug flag to trace loading process.</p>
     */
    private static boolean debug = false;
    
    /**
     * <p>Cache properties for performance.</p>
     */
	private static Properties cacheProps = new Properties();
	
	/**
	 * <p>First time requires initialization overhead.</p>
	 */
	private static boolean firstTime = true;
    
    /**
     * Default columns per line.
     */
    private static final int DEFAULT_LINE_LENGTH = 80;
	
	/**
	 * <p>Check to see if debugging enabled by property.</p>
	 * 
	 * <p>Use try/catch block to support applets, which throws
     * SecurityException out of this code.</p>
	 * 
	 */
    static {
        try {
            String val = SecuritySupport.getSystemProperty("jaxp.debug");
            // Allow simply setting the prop to turn on debug
            debug = val != null && (! "false".equals(val));
        } catch (Exception x) {
            debug = false;
        }
    }
    
    private FactoryFinder() {}

	/**
	 * <p>Output debugging messages.</p>
	 * 
	 * @param msg <code>String</code> to print to <code>stderr</code>.
	 */
    private static void debugPrintln(String msg) {
        if (debug) {
            System.err.println(
            	CLASS_NAME
            	+ ":"
            	+ msg);
        }
    }

    /**
     * <p>Find the appropriate <code>ClassLoader</code> to use.</p>
     * 
     * <p>The context ClassLoader is prefered.</p>
     * 
     * @return <code>ClassLoader</code> to use.
     * 
     * @throws ConfigurationError If a valid <code>ClassLoader</code> cannot be identified. 
     */
    private static ClassLoader findClassLoader()
        throws ConfigurationError {
        ClassLoader classLoader;

        // Figure out which ClassLoader to use for loading the provider
        // class.  If there is a Context ClassLoader then use it.

        classLoader = SecuritySupport.getContextClassLoader();            

        if (debug) debugPrintln(
            "Using context class loader: "
            + classLoader);

        if (classLoader == null) {
            // if we have no Context ClassLoader
            // so use the current ClassLoader
            classLoader = FactoryFinder.class.getClassLoader();
            if (debug) debugPrintln(
                "Using the class loader of FactoryFinder: "
                + classLoader);                
        }
                    
        return classLoader;
    }

    /**
     * <p>Create an instance of a class using the specified ClassLoader.</p>
     * 
     * @param className Name of class to create.
     * @param classLoader ClassLoader to use to create named class.
     * 
     * @return New instance of specified class created using the specified ClassLoader.
     * 
     * @throws ConfigurationError If class could not be created.
     */
    static Object newInstance(
    	String className,
        ClassLoader classLoader)
        throws ConfigurationError {
        	
        try {
            Class spiClass;
            if (classLoader == null) {
                spiClass = Class.forName(className);
            } else {
                spiClass = classLoader.loadClass(className);
            }
            
            if (debug) {
            	debugPrintln("Loaded " + className + " from " + which(spiClass));
            }
             
            return spiClass.newInstance();
        } catch (ClassNotFoundException x) {
            throw new ConfigurationError(
                "Provider " + className + " not found", x);
        } catch (Exception x) {
            throw new ConfigurationError(
                "Provider " + className + " could not be instantiated: " + x,
                x);
        }
    }

    /**
     * Finds the implementation Class object in the specified order.  Main
     * entry point.
     * Package private so this code can be shared.
     *
     * @param factoryId Name of the factory to find, same as a property name
     * @param fallbackClassName Implementation class name, if nothing else is found.  Use null to mean no fallback.
     *
     * @return Class Object of factory, never null
     * 
     * @throws ConfigurationError If Class cannot be found.
     */
    static Object find(String factoryId, String fallbackClassName)
        throws ConfigurationError {
        	
        ClassLoader classLoader = findClassLoader();

        // Use the system property first
        try {
            String systemProp = SecuritySupport.getSystemProperty(factoryId);
            if (systemProp != null && systemProp.length() > 0) {
                if (debug) debugPrintln("found " + systemProp + " in the system property " + factoryId);
                return newInstance(systemProp, classLoader);
            }
        } catch (SecurityException se) {
        	; // NOP, explicitly ignore SecurityException
        }

        // try to read from $java.home/lib/jaxp.properties
        try {
            String javah = SecuritySupport.getSystemProperty("java.home");
            String configFile = javah + File.separator + "lib" + File.separator + "jaxp.properties";
			String factoryClassName = null;
			if (firstTime) {
				synchronized (cacheProps) {
					if (firstTime) {
						File f = new File(configFile);
						firstTime = false;
						if (SecuritySupport.doesFileExist(f)) {
							if (debug) debugPrintln("Read properties file " + f);
							cacheProps.load(SecuritySupport.getFileInputStream(f));
						}
					}
				}
			}
			factoryClassName = cacheProps.getProperty(factoryId);
            if (debug) debugPrintln("found " + factoryClassName + " in $java.home/jaxp.properties"); 
			
			if (factoryClassName != null) {
				return newInstance(factoryClassName, classLoader);
			}
        } catch (Exception ex) {
            if (debug) {
            	ex.printStackTrace();
            } 
        }
        
        // Try Jar Service Provider Mechanism
        Object provider = findJarServiceProvider(factoryId);
        if (provider != null) {
            return provider;
        }

        if (fallbackClassName == null) {
            throw new ConfigurationError(
                "Provider for " + factoryId + " cannot be found", null);
        }

        if (debug) debugPrintln("loaded from fallback value: " + fallbackClassName);
        return newInstance(fallbackClassName, classLoader);
    }

    /*
     * Try to find provider using Jar Service Provider Mechanism
     *
     * @return instance of provider class if found or null
     */
    private static Object findJarServiceProvider(String factoryId)
        throws ConfigurationError
    {

        String serviceId = "META-INF/services/" + factoryId;
        InputStream is = null;

        // First try the Context ClassLoader
        ClassLoader cl = SecuritySupport.getContextClassLoader();
        if (cl != null) {
            is = SecuritySupport.getResourceAsStream(cl, serviceId);

            // If no provider found then try the current ClassLoader
            if (is == null) {
                cl = FactoryFinder.class.getClassLoader();
                is = SecuritySupport.getResourceAsStream(cl, serviceId);
            }
        } else {
            // No Context ClassLoader, try the current
            // ClassLoader
            cl = FactoryFinder.class.getClassLoader();
            is = SecuritySupport.getResourceAsStream(cl, serviceId);
        }

        if (is == null) {
            // No provider found
            return null;
        }

        if (debug) debugPrintln("found jar resource=" + serviceId +
               " using ClassLoader: " + cl);

        BufferedReader rd;
        try {
            rd = new BufferedReader(new InputStreamReader(is, "UTF-8"), DEFAULT_LINE_LENGTH);
        } catch (java.io.UnsupportedEncodingException e) {
            rd = new BufferedReader(new InputStreamReader(is), DEFAULT_LINE_LENGTH);
        }
        
        String factoryClassName = null;
        try {
            // XXX Does not handle all possible input as specified by the
            // Jar Service Provider specification
            factoryClassName = rd.readLine();
        } 
        catch (IOException x) {
            // No provider found
            return null;
        }
        finally {
            try { 
                // try to close the reader. 
                rd.close(); 
            } 
            // Ignore the exception. 
            catch (IOException exc) {}
        }

        if (factoryClassName != null &&
            ! "".equals(factoryClassName)) {
            if (debug) debugPrintln("found in resource, value="
                   + factoryClassName);

            return newInstance(factoryClassName, cl);
        }

        // No provider found
        return null;
    }
    
	/**
	 * <p>Configuration Error.</p>
	 */
    static class ConfigurationError extends Error {
        
        private static final long serialVersionUID = -3644413026244211347L;
    	
    	/**
    	 * <p>Exception that caused the error.</p>
    	 */
        private Exception exception;

        /**
         * <p>Construct a new instance with the specified detail string and
         * exception.</p>
         * 
         * @param msg Detail message for this error.
         * @param x Exception that caused the error.
         */
        ConfigurationError(String msg, Exception x) {
            super(msg);
            this.exception = x;
        }

		/**
		 * <p>Get the Exception that caused the error.</p>
		 * 
		 * @return Exception that caused the error.
		 */
        Exception getException() {
            return exception;
        }
    }



    /**
     * Returns the location where the given Class is loaded from.
     * 
     * @param clazz Class to find load location.
     * 
     * @return Location where class would be loaded from.
     */
    private static String which(Class clazz) {
        try {
            String classnameAsResource = clazz.getName().replace('.', '/') + ".class";
    
            ClassLoader loader = clazz.getClassLoader();
            
            URL it;
    
            if (loader != null) {
            	it = loader.getResource(classnameAsResource);
            } else {
            	it = ClassLoader.getSystemResource(classnameAsResource);
            } 
    
            if (it != null) {
            	return it.toString();
            } 
        }
        // The VM ran out of memory or there was some other serious problem. Re-throw.
        catch (VirtualMachineError vme) {
            throw vme;
        }
        // ThreadDeath should always be re-thrown
        catch (ThreadDeath td) {
            throw td;
        }
        catch (Throwable t) {
            // work defensively.
            if (debug) {
            	t.printStackTrace();
            } 
        }
        return "unknown location";
    }
}
