All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.directwebremoting.webwork.DWRAction Maven / Gradle / Ivy

package org.directwebremoting.webwork;

import java.io.UnsupportedEncodingException;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.directwebremoting.util.FakeHttpServletResponse;
import org.directwebremoting.util.LocalUtil;
import org.directwebremoting.util.Logger;

import com.opensymphony.webwork.ServletActionContext;
import com.opensymphony.webwork.dispatcher.DispatcherUtils;
import com.opensymphony.webwork.dispatcher.mapper.ActionMapping;
import com.opensymphony.xwork.ActionContext;
import com.opensymphony.xwork.ActionInvocation;
import com.opensymphony.xwork.ActionProxy;
import com.opensymphony.xwork.ActionProxyFactory;
import com.opensymphony.xwork.Result;
import com.opensymphony.xwork.config.ConfigurationException;
import com.opensymphony.xwork.util.OgnlValueStack;
import com.opensymphony.xwork.util.XWorkContinuationConfig;

/**
 * This class represents the entry point to all WebWork action invocations. It identifies the
 * action to be invoked, prepares the action invocation context and finally wraps the
 * result.
 * You can configure an IDWRActionProcessor through a context-wide initialization parameter
 * dwrActionProcessor that whose methods will be invoked around action invocation.
 *
 * @author Alexandru Popescu
 */
public class DWRAction
{
    /**
     * The log stream
     */
    private static final Logger log = Logger.getLogger(DWRAction.class);

    private static final String DWRACTIONPROCESSOR_INIT_PARAM = "dwrActionProcessor";

    private static DWRAction s_instance;

    private DispatcherUtils m_wwDispatcher;

    private IDWRActionProcessor m_actionProcessor;

    private DWRAction(ServletContext servletContext) throws ServletException
    {
        DispatcherUtils.initialize(servletContext);
        m_wwDispatcher = DispatcherUtils.getInstance();
        m_actionProcessor = loadActionProcessor(servletContext.getInitParameter(DWRACTIONPROCESSOR_INIT_PARAM));
    }

    /**
     * Entry point for all action invocations.
     *
     * @param actionDefinition the identification information for the action
     * @param params action invocation parameters
     * @param request original request
     * @param response original response
     * @param servletContext current ServletContext
     * @return an AjaxResult wrapping invocation result
     *
     * @throws ServletException thrown if the initialization or invocation of the action fails
     */
    public static AjaxResult execute(ActionDefinition actionDefinition, Map params, HttpServletRequest request, HttpServletResponse response, ServletContext servletContext) throws ServletException
    {
        initialize(servletContext);

        return s_instance.doExecute(actionDefinition, params, request, response, servletContext);
    }

    protected AjaxResult doExecute(ActionDefinition actionDefinition, Map params, HttpServletRequest request, HttpServletResponse response, ServletContext servletContext) throws ServletException
    {

        FakeHttpServletResponse actionResponse = new FakeHttpServletResponse();

        if (null != m_actionProcessor)
        {
            m_actionProcessor.preProcess(request, response, actionResponse, params);
        }

        m_wwDispatcher.prepare(request, actionResponse);

        ActionInvocation invocation = invokeAction(m_wwDispatcher, request, actionResponse, servletContext, actionDefinition, params);

        AjaxResult result = null;
        if (actionDefinition.isExecuteResult())
        {
            // HINT: we have output string
            result = getTextResult(actionResponse);
        }
        else
        {
            result = new DefaultAjaxDataResult(invocation.getAction());
        }

        if (null != m_actionProcessor)
        {
            m_actionProcessor.postProcess(request, response, actionResponse, result);
        }

        return result;
    }

    protected ActionInvocation invokeAction(DispatcherUtils du, HttpServletRequest request, HttpServletResponse response, ServletContext context, ActionDefinition actionDefinition, Map params) throws ServletException
    {
        ActionMapping mapping = getActionMapping(actionDefinition, params);
        Map extraContext = du.createContextMap(request, response, mapping, context);

        // If there was a previous value stack, then create a new copy and pass it in to be used by the new Action
        OgnlValueStack stack = (OgnlValueStack) request.getAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY);
        if (null != stack)
        {
            extraContext.put(ActionContext.VALUE_STACK, new OgnlValueStack(stack));
        }

        try
        {
            prepareContinuationAction(request, extraContext);

            ActionProxy proxy = ActionProxyFactory.getFactory().createActionProxy(actionDefinition.getNamespace(), actionDefinition.getAction(), extraContext, actionDefinition.isExecuteResult(), false);
            proxy.setMethod(actionDefinition.getMethod());
            request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY, proxy.getInvocation().getStack());

            // if the ActionMapping says to go straight to a result, do it!
            if (mapping.getResult() != null)
            {
                Result result = mapping.getResult();
                result.execute(proxy.getInvocation());
            }
            else
            {
                proxy.execute();
            }

            return proxy.getInvocation();
        }
        catch (ConfigurationException ce)
        {
            throw new ServletException("Cannot invoke action '" + actionDefinition.getAction() + "' in namespace '" + actionDefinition.getNamespace() + "'", ce);
        }
        catch (Exception e)
        {
            throw new ServletException("Cannot invoke action '" + actionDefinition.getAction() + "' in namespace '" + actionDefinition.getNamespace() + "'", e);
        }
        finally
        {
            // If there was a previous value stack then set it back onto the request
            if (null != stack)
            {
                request.setAttribute(ServletActionContext.WEBWORK_VALUESTACK_KEY, stack);
            }
        }
    }

    protected void prepareContinuationAction(HttpServletRequest request, Map extraContext)
    {
        String id = request.getParameter(XWorkContinuationConfig.CONTINUE_PARAM);
        if (null != id)
        {
            // remove the continue key from the params - we don't want to bother setting
            // on the value stack since we know it won't work. Besides, this breaks devMode!
            Map params = (Map) extraContext.get(ActionContext.PARAMETERS);
            params.remove(XWorkContinuationConfig.CONTINUE_PARAM);

            // and now put the key in the context to be picked up later by XWork
            extraContext.put(XWorkContinuationConfig.CONTINUE_KEY, id);
        }
    }

    protected ActionMapping getActionMapping(ActionDefinition actionDefinition, Map params)
    {
        ActionMapping actionMapping = new ActionMapping(actionDefinition.getAction(), actionDefinition.getNamespace(), actionDefinition.getMethod(), params);

        return actionMapping;
    }

    protected AjaxTextResult getTextResult(FakeHttpServletResponse response)
    {
        DefaultAjaxTextResult result = new DefaultAjaxTextResult();

        String text = null;
        try
        {
            text = response.getContentAsString();
        }
        catch (UnsupportedEncodingException uee)
        {
            log.warn("Cannot retrieve text output as string", uee);
        }

        if (null == text)
        {
            try
            {
                text = response.getCharacterEncoding() != null ? new String(response.getContentAsByteArray(), response.getCharacterEncoding()) : new String(response.getContentAsByteArray());
            }
            catch (UnsupportedEncodingException uee)
            {
                log.warn("Cannot retrieve text output as encoded byte array", uee);
                text = new String(response.getContentAsByteArray());
            }
        }

        result.setText(text);
        return result;
    }

    /**
     * Performs the one time initialization of the singleton DWRAction.
     *
     * @param servletContext
     * @throws ServletException thrown in case the singleton initialization fails
     */
    private static void initialize(ServletContext servletContext) throws ServletException
    {
        synchronized(DWRAction.class)
        {
            if (null == s_instance)
            {
                s_instance = new DWRAction(servletContext);
            }
        }
    }

    /**
     * Tries to instantiate an IDWRActionProcessor if defined in web.xml.
     *
     * @param actionProcessorClassName
     * @return an instance of IDWRActionProcessor if the init-param is defined or null
     * @throws ServletException thrown if the IDWRActionProcessor cannot be loaded and instantiated
     */
    private static IDWRActionProcessor loadActionProcessor(String actionProcessorClassName) throws ServletException
    {
        if (null == actionProcessorClassName || "".equals(actionProcessorClassName))
        {
            return null;
        }

        try
        {
            Class actionProcessorClass = LocalUtil.classForName(actionProcessorClassName);

            return (IDWRActionProcessor) actionProcessorClass.newInstance();
        }
        catch(ClassNotFoundException cnfe)
        {
            throw new ServletException("Cannot load DWRActionProcessor class '" + actionProcessorClassName + "'", cnfe);
        }
        catch(IllegalAccessException iae)
        {
            throw new ServletException("Cannot instantiate DWRActionProcessor class '" + actionProcessorClassName + "'. Default constructor is not visible", iae);
        }
        catch(InstantiationException ie)
        {
            throw new ServletException("Cannot instantiate DWRActionProcessor class '" + actionProcessorClassName + "'. No default constructor found", ie);
        }
        catch(Throwable cause)
        {
            throw new ServletException("Cannot instantiate DWRActionProcessor class '" + actionProcessorClassName + "'", cause);
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy