/*
 * 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 javax.xml.ws.spi;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.PrivilegedAction;
import java.util.Properties;

/**
 * This code is designed to implement the pluggability
 * feature and is designed to both compile and run on JDK version 1.1 and
 * later.  The code also runs both as part of an unbundled jar file and
 * when bundled as part of the JDK.
 * <p/>
 * This class is duplicated for each subpackage so keep it in sync.
 * It is package private and therefore is not exposed as part of the JAXRPC
 * API.
 */
class FactoryFinder {
    /**
     * Set to true for debugging.
     */
    private static final boolean debug = false;

    private static void debugPrintln(String msg) {
        if (debug) {
            System.err.println("Factory Finder:" + msg);
        }
    }

    /**
     * Figure out which ClassLoader to use.  For JDK 1.2 and later use
     * the context ClassLoader.
     *
     * @return the <code>ClassLoader</code>
     * @throws ConfigurationError if this class is unable to work with the
     *                            host JDK
     */
    private static ClassLoader findClassLoader()
            throws ConfigurationError {
        // REVIEW This doPriv block may be unnecessary because this method is private and 
        // the caller already has a doPriv.  I added the doPriv in case someone changes the 
        // visibility of this method to non-private.
        ClassLoader cl = (ClassLoader)
            doPrivileged( new PrivilegedAction() {
                public Object run() {
                
                    Method m = null;

                    try {

                        m = Thread.class.getMethod("getContextClassLoader", (Class []) null);
                    } catch (NoSuchMethodException e) {
                        // Assume that we are running JDK 1.1, use the current ClassLoader
                        debugPrintln("assuming JDK 1.1");
                        if (FactoryFinder.class.getClassLoader() == null) {
                            return ClassLoader.getSystemClassLoader();
                        }
                        return FactoryFinder.class.getClassLoader();
                    }

                    try {
                        return (ClassLoader) m.invoke(Thread.currentThread(), (Object []) null);
                    } catch (IllegalAccessException e) {
                        // assert(false)
                        throw new ConfigurationError("Unexpected IllegalAccessException",
                                e);
                    } catch (InvocationTargetException e) {
                        // assert(e.getTargetException() instanceof SecurityException)
                        throw new ConfigurationError("Unexpected InvocationTargetException",
                                e);
                    }
                }
            }
        );
        return cl;
        
    }

    /**
     * Create an instance of a class using the specified
     * <code>ClassLoader</code>, or if that fails from the
     * <code>ClassLoader</code> that loaded this class.
     *
     * @param className   the name of the class to instantiate
     * @param classLoader a <code>ClassLoader</code> to load the class from
     * @return a new <code>Object</code> that is an instance of the class of
     *         the given name from the given class loader
     * @throws ConfigurationError if the class could not be found or
     *                            instantiated
     */
    private static Object newInstance(String className,
                                      ClassLoader classLoader)
            throws ConfigurationError {
        
        final ClassLoader iClassLoader = classLoader;
        final String iClassName = className;
        
        // REVIEW This doPriv block may be unnecessary because this method is private and 
        // the caller already has a doPriv.  I added the doPriv in case someone changes the 
        // visibility of this method to non-private.
        Object obj = 
            doPrivileged( new PrivilegedAction() {
                public Object run() {
                    try {
                        if (iClassLoader != null) {
                            try {
                                return iClassLoader.loadClass(iClassName).newInstance();
                            } catch (ClassNotFoundException x) {
                                // try again
                            }
                        }
                        return Class.forName(iClassName).newInstance();
                    } catch (ClassNotFoundException x) {
                        throw new ConfigurationError(
                                "Provider " + iClassName + " not found", x);
                    } catch (Exception x) {
                        throw new ConfigurationError(
                                "Provider " + iClassName + " could not be instantiated: " + x,
                                x);
                    }
                }
            });
        return obj;
    }

    /**
     * Finds the implementation Class object in the specified order.  Main
     * entry point.
     *
     * @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 FactoryFinder.ConfigurationError
     *          Package private so this code can be shared.
     */
    static Object find(String factoryId, String fallbackClassName)
            throws ConfigurationError {
        
        final String iFactoryId = factoryId;
        final String iFallbackClassName = fallbackClassName;
        
        Object obj = 
            doPrivileged( new PrivilegedAction() {
                public Object run() {
                    debugPrintln("debug is on");
                    
                    ClassLoader classLoader = findClassLoader();
                    
			        try {
			            // If we are deployed into an OSGi environment, leverage it
                        Class factoryClass;
                        if (FactoryFinder.class.getClassLoader() == null) {
                            factoryClass = Class.forName(iFactoryId);
                        } else {
                            factoryClass = FactoryFinder.class.getClassLoader().loadClass(iFactoryId);
                        }
                        Class spiClass = org.apache.servicemix.specs.locator.OsgiLocator.locate(factoryClass, iFactoryId);
			            if (spiClass != null) {
			                return spiClass.newInstance();
			            }
			        } catch (Throwable e) {
			        }
			
                    // Use the system property first
                    try {
                        String systemProp =
                            System.getProperty(iFactoryId);
                        if (systemProp != null) {
                            debugPrintln("found system property " + systemProp);
                            return newInstance(systemProp, classLoader);
                        }
                    } catch (SecurityException se) {
                    }
                    
                    // try to read from $java.home/lib/xml.properties
                    try {
                        String javah = System.getProperty("java.home");
                        String configFile = javah + File.separator +
                        "lib" + File.separator + "jaxrpc.properties";
                        File f = new File(configFile);
                        if (f.exists()) {
                            Properties props = new Properties();
                            props.load(new FileInputStream(f));
                            String factoryClassName = props.getProperty(iFactoryId);
                            debugPrintln("found java.home property " + factoryClassName);
                            return newInstance(factoryClassName, classLoader);
                        }
                    } catch (Exception ex) {
                        if (debug) ex.printStackTrace();
                    }
                    
                    String serviceId = "META-INF/services/" + iFactoryId;
                    // try to find services in CLASSPATH
                    try {
                        InputStream is = null;
                        if (classLoader == null) {
                            is = ClassLoader.getSystemResourceAsStream(serviceId);
                        } else {
                            is = classLoader.getResourceAsStream(serviceId);
                        }
                        
                        if (is != null) {
                            debugPrintln("found " + serviceId);
                            
                            // Read the service provider name in UTF-8 as specified in
                            // the jar spec.  Unfortunately this fails in Microsoft
                            // VJ++, which does not implement the UTF-8
                            // encoding. Theoretically, we should simply let it fail in
                            // that case, since the JVM is obviously broken if it
                            // doesn't support such a basic standard.  But since there
                            // are still some users attempting to use VJ++ for
                            // development, we have dropped in a fallback which makes a
                            // second attempt using the platform's default encoding. In
                            // VJ++ this is apparently ASCII, which is a subset of
                            // UTF-8... and since the strings we'll be reading here are
                            // also primarily limited to the 7-bit ASCII range (at
                            // least, in English versions), this should work well
                            // enough to keep us on the air until we're ready to
                            // officially decommit from VJ++. [Edited comment from
                            // jkesselm]
                            BufferedReader rd;
                            try {
                                rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                            } catch (java.io.UnsupportedEncodingException e) {
                                rd = new BufferedReader(new InputStreamReader(is));
                            }
                            
                            String factoryClassName = rd.readLine();
                            rd.close();
                            
                            if (factoryClassName != null &&
                                    ! "".equals(factoryClassName)) {
                                debugPrintln("loaded from services: " + factoryClassName);
                                return newInstance(factoryClassName, classLoader);
                            }
                        }
                    } catch (Exception ex) {
                        if (debug) ex.printStackTrace();
                    }
                    
                    if (iFallbackClassName == null) {
                        throw new ConfigurationError(
                                "Provider for " + iFactoryId + " cannot be found", null);
                    }
                    
                    debugPrintln("loaded from fallback value: " + iFallbackClassName);
                    return newInstance(iFallbackClassName, classLoader);
                }
            });
        return obj;
    }

    private static Object doPrivileged(PrivilegedAction action) {
        SecurityManager sm = System.getSecurityManager();
        if (sm == null) {
            return(action.run());
        } else {
            return java.security.AccessController.doPrivileged(action);
        }
    }

    static class ConfigurationError extends Error {
        // fixme: should this be refactored to use the jdk1.4 exception
        // wrapping?

        private Exception exception;

        /**
         * Construct a new instance with the specified detail string and
         * exception.
         *
         * @param msg the Message for this error
         * @param x   an Exception that caused this failure, or null
         */
        ConfigurationError(String msg, Exception x) {
            super(msg);
            this.exception = x;
        }

        Exception getException() {
            return exception;
        }
    }
}
