/*
 * 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.servicemix.executors.impl;

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.
 */
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");
                        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
                        ClassLoader cl = FactoryFinder.class.getClassLoader();
                        if (cl == null) {
                            cl = ClassLoader.getSystemClassLoader();
                        }
                        Class factoryClass = cl.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) {
                    }

                    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;
        }
    }
}
