Package org.directwebremoting.webwork

Source Code of org.directwebremoting.webwork.DWRAction

/*
* Copyright 2006 Alexandru Popescu
*
* Licensed 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.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.apache.commons.logging.LogFactory;
import org.apache.commons.logging.Log;
import org.directwebremoting.util.FakeHttpServletResponse;
import org.directwebremoting.util.LocalUtil;

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 <code>IDWRActionProcessor</code> through a context-wide initialization parameter
* <code>dwrActionProcessor</code> that whose methods will be invoked around action invocation.
*
* @author <a href='mailto:the_mindstorm[at]evolva[dot]ro'>Alexandru Popescu</a>
*/
public class DWRAction
{
    /**
     * @param servletContext
     * @throws ServletException
     */
    private DWRAction(ServletContext servletContext) throws ServletException
    {
        DispatcherUtils.initialize(servletContext);
        wwDispatcher = DispatcherUtils.getInstance();
        actionProcessor = loadActionProcessor(servletContext.getInitParameter(DWRACTIONPROCESSOR_INIT_PARAM));
    }

    /**
     *
     */
    protected AjaxResult doExecute(ActionDefinition actionDefinition, Map<String, String> params, HttpServletRequest request, HttpServletResponse response, ServletContext servletContext) throws ServletException
    {
        FakeHttpServletResponse actionResponse = new FakeHttpServletResponse();

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

        wwDispatcher.prepare(request, actionResponse);

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

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

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

        return result;
    }

    /**
     *
     */
    @SuppressWarnings("unchecked")
    protected ActionInvocation invokeAction(DispatcherUtils du, HttpServletRequest request, HttpServletResponse response, ServletContext context, ActionDefinition actionDefinition, Map<String, String> params) throws ServletException
    {
        ActionMapping mapping = getActionMapping(actionDefinition, params);
        Map<String, Object> 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);
            }
        }
    }

    /**
     *
     */
    @SuppressWarnings("unchecked")
    protected void prepareContinuationAction(HttpServletRequest request, Map<String, Object> 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<String, String> params = (Map<String, String>) 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<String, String> 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;
    }

    /**
     * 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 <code>ServletContext</code>
     * @return an <code>AjaxResult</code> wrapping invocation result
     * @throws ServletException thrown if the initialization or invocation of the action fails
     */
    public static AjaxResult execute(ActionDefinition actionDefinition, Map<String, String> params, HttpServletRequest request, HttpServletResponse response, ServletContext servletContext) throws ServletException
    {
        initialize(servletContext);

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

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

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

        IDWRActionProcessor reply = LocalUtil.classNewInstance("DWRActionProcessor", actionProcessorClassName, IDWRActionProcessor.class);
        if (reply == null)
        {
            throw new ServletException("Cannot load DWRActionProcessor class '" + actionProcessorClassName + "'");
        }

        return reply;
    }

    /**
     * The log stream
     */
    private static final Log log = LogFactory.getLog(DWRAction.class);

    private static final String DWRACTIONPROCESSOR_INIT_PARAM = "dwrActionProcessor";

    private static DWRAction instance;

    private DispatcherUtils wwDispatcher;

    private IDWRActionProcessor actionProcessor;
}
TOP

Related Classes of org.directwebremoting.webwork.DWRAction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.