/* * $Id: ActionListenerImpl.java 664382 2008-06-07 20:45:12Z pbenedict $ * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.struts.faces.application; import javax.faces.component.ActionSource; import javax.faces.component.UIComponent; import javax.faces.component.UIForm; import javax.faces.context.FacesContext; import javax.faces.event.AbortProcessingException; import javax.faces.event.ActionEvent; import javax.faces.event.ActionListener; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.struts.Globals; import org.apache.struts.action.ActionServlet; import org.apache.struts.action.RequestProcessor; import org.apache.struts.config.ModuleConfig; import org.apache.struts.faces.Constants; import org.apache.struts.faces.component.FormComponent; import org.apache.struts.util.RequestUtils; import org.apache.struts.util.ModuleUtils; /** * <p>Concrete implementation of <code>ActionListener</code> that replaces * the default provided implementation. It converts application-level events * into execution of the corresponding Struts request processing lifecycle. * </p> * * @version $Rev: 664382 $ $Date: 2008-06-07 22:45:12 +0200 (Sam, 07 jui 2008) $ */ public final class ActionListenerImpl implements ActionListener { // ------------------------------------------------------------ Constructors /** * <p>Construct a new default <code>ActionListener</code> instance, * passing it the previously configured one.</p> * * @param original Original default <code>ActionListener</code> * * @exception NullPointerException if <code>original</code> * is <code>null</code> */ public ActionListenerImpl(ActionListener original) { if (original == null) { throw new NullPointerException(); } this.original = original; if (log.isInfoEnabled()) { log.info("Create ActionListener wrapping instance of type '" + original.getClass().getName() + "'"); } } // ------------------------------------------------------ Instance Variables /** * <p>The logger for this instance.</p> */ private static final Log log = LogFactory.getLog(ActionListenerImpl.class); /** * <p>The previously configured <code>ActionListener</code> instance.</p> */ private ActionListener original; // ---------------------------------------------------------- Public Methods /** * <p>Process the specified <code>ActionEvent</code>.</p> * * @param event The <code>ActionEvent</code> to be processed * * @exception AbortProcessingException to signal that no further * event processing should be performed */ public void processAction(ActionEvent event) throws AbortProcessingException { // If this is an immediate action, or we are NOT nested in a // Struts form, perform the standard processing UIComponent component = event.getComponent(); ActionSource source = (ActionSource) component; boolean standard = source.isImmediate(); if (!standard) { UIComponent parent = component.getParent(); while (parent != null) { if (parent instanceof UIForm) { if (!(parent instanceof FormComponent)) { standard = true; } break; } parent = parent.getParent(); } } if (standard) { if (log.isDebugEnabled()) { log.debug("Performing standard handling for event " + "from source component '" + component.getId() + "'"); } original.processAction(event); return; } // Acquire Servlet API Object References FacesContext context = FacesContext.getCurrentInstance(); ServletContext servletContext = (ServletContext) context.getExternalContext().getContext(); HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest(); HttpServletResponse response = (HttpServletResponse) context.getExternalContext().getResponse(); // Log this event if requested if (log.isDebugEnabled()) { log.debug("Performing Struts form submit for event " + " from source component '" + component.getId() + "'"); } // Invoke the appropriate request processor for this request try { request.setAttribute(Constants.ACTION_EVENT_KEY, event); ModuleUtils.getInstance().selectModule(request, servletContext); ModuleConfig moduleConfig = (ModuleConfig) request.getAttribute(Globals.MODULE_KEY); if (log.isTraceEnabled()) { log.trace("Assigned to module with prefix '" + moduleConfig.getPrefix() + "'"); } RequestProcessor processor = getRequestProcessor(moduleConfig, servletContext); if (log.isTraceEnabled()) { log.trace("Invoking request processor instance " + processor); } processor.process(request, response); context.responseComplete(); } catch (Exception e) { log.error("Exception processing action event " + event, e); } finally { request.removeAttribute(Constants.ACTION_EVENT_KEY); } } // ------------------------------------------------------ Protected Methods /** * <p>Look up and return the <code>RequestProcessor</code> responsible for * the specified module, creating a new one if necessary. This method is * based on the corresponding code in <code>ActionServlet</code>, which * cannot be used directly because it is a protected method.</p> * * @param config The module configuration for which to * acquire and return a RequestProcessor * @param context The <code>ServletContext</code> instance * for this web application * * @exception IllegalStateException if we cannot instantiate a * RequestProcessor instance */ protected RequestProcessor getRequestProcessor(ModuleConfig config, ServletContext context) { String key = Globals.REQUEST_PROCESSOR_KEY + config.getPrefix(); RequestProcessor processor = (RequestProcessor) context.getAttribute(key); if (processor == null) { try { if (log.isDebugEnabled()) { log.debug("Instantiating RequestProcessor of class " + config.getControllerConfig().getProcessorClass()); } ActionServlet servlet = (ActionServlet) context.getAttribute(Globals.ACTION_SERVLET_KEY); processor = (RequestProcessor) RequestUtils.applicationInstance( config.getControllerConfig().getProcessorClass()); processor.init(servlet, config); context.setAttribute(key, processor); } catch (Exception e) { log.error("Cannot instantiate RequestProcessor of class " + config.getControllerConfig().getProcessorClass(), e); IllegalStateException e2 = new IllegalStateException( "Cannot initialize RequestProcessor of class " + config.getControllerConfig().getProcessorClass()); e2.initCause(e); throw e2; } } return (processor); } }