import java.io.UnsupportedEncodingException; import java.util.HashMap; 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 org.apache.struts2.ServletActionContext; import org.apache.struts2.dispatcher.Dispatcher; import org.apache.struts2.dispatcher.mapper.ActionMapping; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.ActionProxy; import com.opensymphony.xwork2.ActionProxyFactory; import com.opensymphony.xwork2.Result; import com.opensymphony.xwork2.config.Configuration; import com.opensymphony.xwork2.config.ConfigurationException; import com.opensymphony.xwork2.util.OgnlValueStack; /** * 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 */ 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 Dispatcher m_wwDispatcher; private IDWRActionProcessor m_actionProcessor; @SuppressWarnings("unchecked") private DWRAction(ServletContext servletContext) throws ServletException { // Dispatcher.initialize(servletContext);
m_wwDispatcher = Dispatcher.getInstance(); if(m_wwDispatcher==null) { m_wwDispatcher = new Dispatcher(servletContext, new HashMap()); m_wwDispatcher.init(); Dispatcher.setInstance(m_wwDispatcher); } 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; } @SuppressWarnings("unchecked") protected ActionInvocation invokeAction(Dispatcher 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.STRUTS_VALUESTACK_KEY); if (null != stack) { extraContext.put(ActionContext.VALUE_STACK, new OgnlValueStack(stack)); } try { prepareContinuationAction(request, extraContext); Configuration config = du.getConfigurationManager().getConfiguration(); ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy( mapping.getNamespace(), mapping.getName(), extraContext, actionDefinition.isExecuteResult(), false); proxy.setMethod(actionDefinition.getMethod()); request.setAttribute(ServletActionContext.STRUTS_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.STRUTS_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); } } }
|