/*
 * 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.axis2.rpc.receivers.ejb;

import org.apache.axis2.AxisFault;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.util.threadpool.DefaultThreadFactory;

import javax.naming.Context;
import javax.naming.InitialContext;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class EJBUtil {
    public static final java.lang.String EJB_JNDI_NAME = "beanJndiName";
    public static final java.lang.String EJB_HOME_INTERFACE_NAME = "homeInterfaceName";
    public static final java.lang.String EJB_REMOTE_INTERFACE_NAME = "remoteInterfaceName";
    public static final java.lang.String EJB_LOCAL_HOME_INTERFACE_NAME = "localHomeInterfaceName";
    public static final java.lang.String EJB_LOCAL_INTERFACE_NAME = "localInterfaceName";
    public static final java.lang.String EJB_INITIAL_CONTEXT_FACTORY = "jndiContextClass";
    public static final java.lang.String EJB_PROVIDER_URL = "providerUrl";
    public static final java.lang.String EJB_JNDI_USERNAME = "jndiUser";
    public static final java.lang.String EJB_JNDI_PASSWORD = "jndiPassword";

    private static ExecutorService workerPool = null;

    static {
        workerPool =
                new ThreadPoolExecutor(1, 50, 150L, TimeUnit.SECONDS, new LinkedBlockingQueue(),
                                       new DefaultThreadFactory(
                                               new ThreadGroup("EJB provider thread group"),
                                               "EJBProvider"));
    }

    /**
     * Return a object which implements the service.
     *
     * @param msgContext the message context
     * @return an object that implements the service
     * @throws AxisFault if fails
     */
    protected static Object makeNewServiceObject(MessageContext msgContext) throws AxisFault {
        CountDownLatch startLatch = new CountDownLatch(1);
        CountDownLatch stopLatch = new CountDownLatch(1);
        EJBClientWorker worker = new EJBClientWorker(msgContext, startLatch, stopLatch);
        workerPool.execute(worker);
        startLatch.countDown();
        try {
            stopLatch.await();
        } catch (InterruptedException e) {
            throw AxisFault.makeFault(e);
        }

        if (worker.getException() != null) {
            throw AxisFault.makeFault(worker.getException());
        }

        return worker.getReturnedValue();
    }

    private static class EJBClientWorker implements Runnable {

        private MessageContext msgContext = null;
        private CountDownLatch startLatch = null;
        private CountDownLatch stopLatch = null;
        protected static final Class[] empty_class_array = new Class[0];
        protected static final Object[] empty_object_array = new Object[0];
        private static InitialContext cached_context = null;
        private Exception exception = null;
        private Object returnedValue = null;

        public EJBClientWorker(MessageContext msgContext, CountDownLatch startLatch,
                               CountDownLatch stopLatch) {
            this.msgContext = msgContext;
            this.startLatch = startLatch;
            this.stopLatch = stopLatch;
        }

        public void run() {
            try {
                startLatch.await();
                final AxisService service = msgContext.getAxisService();
                AccessController.doPrivileged(
                        new PrivilegedAction() {
                            public Object run() {
                                Thread.currentThread()
                                        .setContextClassLoader(service.getClassLoader());
                                return null;
                            }
                        }
                );
                Parameter remoteHomeName = service.getParameter(EJB_HOME_INTERFACE_NAME);
                Parameter localHomeName = service.getParameter(EJB_LOCAL_HOME_INTERFACE_NAME);
                Parameter jndiName = service.getParameter(EJB_JNDI_NAME);
                Parameter homeName = (remoteHomeName != null ? remoteHomeName : localHomeName);

                if (jndiName == null || jndiName.getValue() == null) {
                    throw new AxisFault("jndi name is not specified");
                } else if (homeName == null || homeName.getValue() == null) {
                    // cannot find both remote home and local home
                    throw new AxisFault("ejb remote/local home class name is not specified");
                }

                // we create either the ejb using either the RemoteHome or LocalHome object
                if (remoteHomeName != null)
                    returnedValue = createRemoteEJB(msgContext,
                                                    ((String)jndiName.getValue()).trim(),
                                                    ((String)homeName.getValue()).trim());
                else
                    returnedValue = createLocalEJB(msgContext, ((String)jndiName.getValue()).trim(),
                                                   ((String)homeName.getValue()).trim());
            } catch (Exception e) {
                e.printStackTrace();
                exception = e;
            } finally {
                stopLatch.countDown();
            }
        }

        /**
         * Create an EJB using a remote home object
         *
         * @param msgContext   the message context
         * @param beanJndiName The JNDI name of the EJB remote home class
         * @param homeName     the name of the home interface class
         * @return an EJB
         * @throws Exception If fails
         */
        private Object createRemoteEJB(MessageContext msgContext, String beanJndiName,
                                       String homeName) throws Exception {
            // Get the EJB Home object from JNDI
            Object ejbHome = getEJBHome(msgContext.getAxisService(), beanJndiName);
            Class cls = getContextClassLoader().loadClass(homeName);
            Object ehome = javax.rmi.PortableRemoteObject.narrow(ejbHome, cls);

            // Invoke the create method of the ejbHome class without actually
            // touching any EJB classes (i.e. no cast to EJBHome)
            Method createMethod = cls.getMethod("create", empty_class_array);

            return createMethod.invoke(ehome, empty_object_array);
        }

        /**
         * Create an EJB using a local home object
         *
         * @param msgContext   the message context
         * @param beanJndiName The JNDI name of the EJB local home class
         * @param homeName     the name of the home interface class
         * @return an EJB
         * @throws Exception if fails
         */
        private Object createLocalEJB(MessageContext msgContext, String beanJndiName,
                                      String homeName)
                throws Exception {
            // Get the EJB Home object from JNDI
            Object ejbHome = getEJBHome(msgContext.getAxisService(), beanJndiName);

            // the home object is a local home object
            Object ehome;

            Class cls = getContextClassLoader().loadClass(homeName);

            if (cls.isInstance(ejbHome))
                ehome = ejbHome;
            else {
                throw new ClassCastException("bad ejb home type");
            }

            // Invoke the create method of the ejbHome class without actually
            // touching any EJB classes (i.e. no cast to EJBLocalHome)
            Method createMethod = cls.getMethod("create", empty_class_array);

            return createMethod.invoke(ehome, empty_object_array);
        }

        /**
         * Common routine to do the JNDI lookup on the Home interface object username and password
         * for jndi lookup are got from the configuration or from the messageContext if not found in
         * the configuration
         *
         * @param service      AxisService object
         * @param beanJndiName JNDI name of the EJB home object
         * @return EJB home object
         * @throws AxisFault If fals
         */
        private Object getEJBHome(AxisService service, String beanJndiName) throws AxisFault {
            Object ejbHome;

            // Set up an InitialContext and use it get the beanJndiName from JNDI
            try {
                Properties properties = null;

                // collect all the properties we need to access JNDI:
                // username, password, factoryclass, contextUrl

                // username
                Parameter username = service.getParameter(EJB_JNDI_USERNAME);
                if (username != null) {
                    if (properties == null)
                        properties = new Properties();
                    properties.setProperty(Context.SECURITY_PRINCIPAL,
                                           ((String)username.getValue()).trim());
                }

                // password
                Parameter password = service.getParameter(EJB_JNDI_PASSWORD);
                if (password != null) {
                    if (properties == null)
                        properties = new Properties();
                    properties.setProperty(Context.SECURITY_CREDENTIALS,
                                           ((String)password.getValue()).trim());
                }

                // factory class
                Parameter factoryClass = service.getParameter(EJB_INITIAL_CONTEXT_FACTORY);
                if (factoryClass != null) {
                    if (properties == null)
                        properties = new Properties();
                    properties.setProperty(Context.INITIAL_CONTEXT_FACTORY,
                                           ((String)factoryClass.getValue()).trim());
                }

                // contextUrl
                Parameter contextUrl = service.getParameter(EJB_PROVIDER_URL);
                if (contextUrl != null) {
                    if (properties == null)
                        properties = new Properties();
                    properties.setProperty(Context.PROVIDER_URL,
                                           ((String)contextUrl.getValue()).trim());
                }

                // get context using these properties
                InitialContext context = getContext(properties);

                // if we didn't get a context, fail
                if (context == null)
                    throw new AxisFault("cannot create initial context");

                ejbHome = getEJBHome(context, beanJndiName);

                if (ejbHome == null)
                    throw new AxisFault("cannot find jndi home");
            }
            catch (Exception exception) {
                throw AxisFault.makeFault(exception);
            }

            return ejbHome;
        }

        private InitialContext getCachedContext()
                throws javax.naming.NamingException {
            if (cached_context == null)
                cached_context = new InitialContext();
            return cached_context;
        }


        private InitialContext getContext(Properties properties)
                throws AxisFault, javax.naming.NamingException {
            return ((properties == null)
                    ? getCachedContext()
                    : new InitialContext(properties));
        }

        private Object getEJBHome(InitialContext context, String beanJndiName)
                throws AxisFault, javax.naming.NamingException {
            return context.lookup(beanJndiName);
        }

        private ClassLoader getContextClassLoader() {
            return (ClassLoader)AccessController.doPrivileged(
                    new PrivilegedAction() {
                        public Object run() {
                            return Thread.currentThread().getContextClassLoader();
                        }
                    }
            );
        }

        public Exception getException() {
            return exception;
        }

        public Object getReturnedValue() {
            return returnedValue;
        }
    }
}
