/**
 * ÀÌ ¼Ò½º´Â Spring ÇÁ·¹ÀÓ¿öÅ© ¿öÅ©ºÏ¿¡¼­ »ç¿ëÇÑ ¿¹Á¦ ¼Ò½ºÀÔ´Ï´Ù. 
 * ÀÌ ¼Ò½º´Â ¸ðµç °³¹ßÀÚµéÀÌ ÀÚÀ¯·Ó°Ô ¼öÁ¤ ¹× ¹èÆ÷ÇÒ ¼ö ÀÖ½À´Ï´Ù. 
 * ´Ü, ÀÌ ¼Ò½º¸¦ ±â¹ÝÀ¸·Î »õ·Î¿î ¾ÖÇÃ¸®ÄÉÀÌ¼ÇÀ» °³¹ßÇÒ °æ¿ì ÃâÃ³¸¦ ¸í½ÃÇØ ÁÖ½Ã¸é µË´Ï´Ù. 
 */
package net.javajigi.servicelocator;

import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

import javax.ejb.EJBLocalHome;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;

import net.javajigi.common.util.MailUtil;
import net.javajigi.common.util.StringUtil;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * ÁÖ¼®À» ³Ö¾î ÁÖ¼¼¿ä. ¹è°¡ °íÆÄ¿ä.
 * 
 * @author ¹ÚÀç¼º(ÀÚ¹ÙÁö±â, javajigi@gmail.com)
 */
public class ServiceLocator {
    protected static final Log logger = LogFactory.getLog(ServiceLocator.class);

    private InitialContext initialContext;

    private Map cache;

    private static ServiceLocator _instance;

    static {
        _instance = new ServiceLocator();
    }

    private ServiceLocator() throws ServiceLocatorException {
        try {
            initialContext = getContext();
            cache = Collections.synchronizedMap(new HashMap());
        } catch (NamingException e) {
            if (logger.isErrorEnabled()) {
                logger.error(e.getMessage(), e);
            }

            throw new ServiceLocatorException(e);
        } catch (Exception e) {
            if (logger.isErrorEnabled()) {
                logger.error(e.getMessage(), e);
            }

            throw new ServiceLocatorException(e);
        }
    }

    static public ServiceLocator getInstance() {
        return _instance;
    }

    public EJBLocalHome getLocalHome(String jndiHomeName)
            throws ServiceLocatorException {
        EJBLocalHome localHome = null;
        try {
            if (cache.containsKey(jndiHomeName)) {
                localHome = (EJBLocalHome) cache.get(jndiHomeName);
            } else {
                localHome = (EJBLocalHome) initialContext.lookup(jndiHomeName);
                cache.put(jndiHomeName, localHome);
            }
        } catch (NamingException e) {
            if (logger.isErrorEnabled()) {
                logger.error(e.getMessage(), e);
            }

            MailUtil.sendHtmlMessage("User Management System Error", StringUtil
                    .stackTraceToString(e));

            throw new ServiceLocatorException(e);
        } catch (Exception e) {
            if (logger.isErrorEnabled()) {
                logger.error(e.getMessage(), e);
            }

            MailUtil.sendHtmlMessage("User Management System Error", StringUtil
                    .stackTraceToString(e));

            throw new ServiceLocatorException(e);
        }
        return localHome;
    }

    public Object getRemoteHome(String jndiHomeName, Class homeClassName)
            throws ServiceLocatorException {
        Object remoteHome = null;
        try {
            if (cache.containsKey(jndiHomeName)) {
                remoteHome = cache.get(jndiHomeName);
            } else {
                Object objref = initialContext.lookup(jndiHomeName);
                remoteHome = PortableRemoteObject.narrow(objref, homeClassName);
                cache.put(jndiHomeName, remoteHome);
            }
        } catch (NamingException e) {
            if (logger.isErrorEnabled()) {
                logger.error(e.getMessage(), e);
            }

            throw new ServiceLocatorException(e);
        } catch (Exception e) {
            if (logger.isErrorEnabled()) {
                logger.error(e.getMessage(), e);
            }

            throw new ServiceLocatorException(e);
        }
        return remoteHome;
    }

    private InitialContext getContext() throws NamingException {
        Hashtable props = new Hashtable();

        // ----------------------JBOSS
        props.put(InitialContext.INITIAL_CONTEXT_FACTORY,
                "org.jnp.interfaces.NamingContextFactory");
        props.put(InitialContext.PROVIDER_URL, "jnp://127.0.0.1:1099");
        // ----------------------JBOSS

        InitialContext initialContext = new InitialContext(props);

        return initialContext;
    }
}
