package org.seasar.axis.server;

import java.util.HashMap;
import java.util.Map;

import org.apache.axis.AxisFault;
import org.apache.axis.MessageContext;
import org.apache.axis.components.logger.LogFactory;
import org.apache.axis.handlers.BasicHandler;
import org.apache.axis.handlers.soap.SOAPService;
import org.apache.axis.transport.http.HTTPConstants;
import org.apache.axis.utils.Messages;
import org.apache.commons.logging.Log;
import org.seasar.framework.container.ComponentDef;
import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.SingletonS2ContainerFactory;

public class S2Handler extends BasicHandler {
    private static final Log logger = LogFactory.getLog(S2Handler.class
            .getName());
    private final Map soapServices = new HashMap();

    public void invoke(final MessageContext msgContext) throws AxisFault {
        try {
            setupService(msgContext);
        }
        catch (final Exception e) {
            logger.error(Messages.getMessage("exception00"), e);
            throw AxisFault.makeFault(e);
        }
    }

    protected void setupService(final MessageContext msgContext)
            throws Exception {
        final String componentName = getComponentName(msgContext);
        if (componentName == null) {
            return;
        }

        final S2Container container = SingletonS2ContainerFactory
                .getContainer();
        if (!container.hasComponentDef(componentName)) {
            return;
        }

        msgContext.setService(getService(msgContext, container, componentName));
    }

    protected String getComponentName(final MessageContext msgContext) {
        final String pathInfo = (String) msgContext
                .getProperty(HTTPConstants.MC_HTTP_SERVLETPATHINFO);
        if (pathInfo == null || pathInfo.length() == 0) {
            return null;
        }

        return pathInfo.substring(1).replace('/', '.');
    }

    protected SOAPService getService(final MessageContext msgContext,
            final S2Container container, final String componentName)
            throws AxisFault {
        final ComponentDef componentDef = container
                .getComponentDef(componentName);
        SOAPService soapService = (SOAPService) soapServices.get(componentDef);
        if (soapService == null) {
            soapService = createService(msgContext, componentDef);
            soapServices.put(componentDef, soapService);
        }

        soapService.setEngine(msgContext.getAxisEngine());
        soapService.init(); // ??

        return soapService;
    }

    protected SOAPService createService(final MessageContext msgContext,
            final ComponentDef componentDef) throws AxisFault {
        final SOAPService soapService = new SOAPService(new S2Provider());
        final String componentClassName = componentDef.getComponentClass()
                .getName();
        soapService.setName(componentClassName);
        soapService.setOption(S2Provider.OPTION_CLASSNAME, componentClassName);
        soapService.setOption(S2Provider.OPTION_COMPONENT_DEF, componentDef);
        soapService.getInitializedServiceDesc(msgContext);

        return soapService;
    }
}