View Javadoc

1   /*
2    * $Id: ActionListenerImpl.java 471754 2006-11-06 14:55:09Z husted $
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  package org.apache.struts.faces.application;
23  
24  
25  import javax.faces.component.ActionSource;
26  import javax.faces.component.UIComponent;
27  import javax.faces.component.UIForm;
28  import javax.faces.context.FacesContext;
29  import javax.faces.event.AbortProcessingException;
30  import javax.faces.event.ActionEvent;
31  import javax.faces.event.ActionListener;
32  import javax.servlet.ServletContext;
33  import javax.servlet.http.HttpServletRequest;
34  import javax.servlet.http.HttpServletResponse;
35  import org.apache.commons.logging.Log;
36  import org.apache.commons.logging.LogFactory;
37  import org.apache.struts.Globals;
38  import org.apache.struts.action.ActionServlet;
39  import org.apache.struts.action.RequestProcessor;
40  import org.apache.struts.config.ModuleConfig;
41  import org.apache.struts.faces.Constants;
42  import org.apache.struts.faces.component.FormComponent;
43  import org.apache.struts.util.RequestUtils;
44  import org.apache.struts.util.ModuleUtils;
45  
46  
47  /**
48   * <p>Concrete implementation of <code>ActionListener</code> that replaces
49   * the default provided implementation.  It converts application-level events
50   * into execution of the corresponding Struts request processing lifecycle.
51   * </p>
52   *
53   * @version $Rev: 471754 $ $Date: 2006-11-06 08:55:09 -0600 (Mon, 06 Nov 2006) $
54   */
55  
56  public final class ActionListenerImpl implements ActionListener {
57  
58  
59      // ------------------------------------------------------------ Constructors
60  
61  
62      /**
63       * <p>Construct a new default <code>ActionListener</code> instance,
64       * passing it the previously configured one.</p>
65       *
66       * @param original Original default <code>ActionListener</code>
67       *
68       * @exception NullPointerException if <code>original</code>
69       *  is <code>null</code>
70       */
71      public ActionListenerImpl(ActionListener original) {
72  
73          if (original == null) {
74              throw new NullPointerException();
75          }
76          this.original = original;
77          if (log.isInfoEnabled()) {
78              log.info("Create ActionListener wrapping instance of type '" +
79                       original.getClass().getName() + "'");
80          }
81  
82      }
83  
84  
85  
86      // ------------------------------------------------------ Instance Variables
87  
88  
89      /**
90       * <p>The logger for this instance.</p>
91       */
92      private static final Log log = LogFactory.getLog(ActionListenerImpl.class);
93  
94  
95      /**
96       * <p>The previously configured <code>ActionListener</code> instance.</p>
97       */
98      private ActionListener original;
99  
100 
101     // ---------------------------------------------------------- Public Methods
102 
103 
104     /**
105      * <p>Process the specified <code>ActionEvent</code>.</p>
106      *
107      * @param event The <code>ActionEvent</code> to be processed
108      *
109      * @exception AbortProcessingException to signal that no further
110      *  event processing should be performed
111      */
112     public void processAction(ActionEvent event)
113         throws AbortProcessingException {
114 
115         // If this is an immediate action, or we are NOT nested in a
116         // Struts form, perform the standard processing
117         UIComponent component = event.getComponent();
118         ActionSource source = (ActionSource) component;
119         boolean standard = source.isImmediate();
120         if (!standard) {
121             UIComponent parent = component.getParent();
122             while (parent != null) {
123                 if (parent instanceof UIForm) {
124                     if (!(parent instanceof FormComponent)) {
125                         standard = true;
126                     }
127                     break;
128                 }
129                 parent = parent.getParent();
130             }
131         }
132         if (standard) {
133             if (log.isDebugEnabled()) {
134                 log.debug("Performing standard handling for event " +
135                           "from source component '" + component.getId() + "'");
136             }
137             original.processAction(event);
138             return;
139         }
140 
141 
142         // Acquire Servlet API Object References
143         FacesContext context = FacesContext.getCurrentInstance();
144         ServletContext servletContext = (ServletContext)
145             context.getExternalContext().getContext();
146         HttpServletRequest request = (HttpServletRequest)
147             context.getExternalContext().getRequest();
148         HttpServletResponse response = (HttpServletResponse)
149             context.getExternalContext().getResponse();
150 
151         // Log this event if requested
152         if (log.isDebugEnabled()) {
153             log.debug("Performing Struts form submit for event " +
154                       " from source component '" +
155                       component.getId() + "'");
156         }
157 
158         // Invoke the appropriate request processor for this request
159         try {
160             request.setAttribute(Constants.ACTION_EVENT_KEY, event);
161             ModuleUtils.getInstance().selectModule(request, servletContext);
162             ModuleConfig moduleConfig = (ModuleConfig)
163                 request.getAttribute(Globals.MODULE_KEY);
164             if (log.isTraceEnabled()) {
165                 log.trace("Assigned to module with prefix '" +
166                           moduleConfig.getPrefix() + "'");
167             }
168             RequestProcessor processor =
169                 getRequestProcessor(moduleConfig, servletContext);
170             if (log.isTraceEnabled()) {
171                 log.trace("Invoking request processor instance " + processor);
172             }
173             processor.process(request, response);
174             context.responseComplete();
175         } catch (Exception e) {
176             log.error("Exception processing action event " + event, e);
177         } finally {
178             request.removeAttribute(Constants.ACTION_EVENT_KEY);
179         }
180 
181     }
182 
183 
184     // ------------------------------------------------------ Protected Methods
185 
186 
187     /**
188      * <p>Look up and return the <code>RequestProcessor</code> responsible for
189      * the specified module, creating a new one if necessary.  This method is
190      * based on the corresponding code in <code>ActionServlet</code>, which
191      * cannot be used directly because it is a protected method.</p>
192      *
193      * @param config The module configuration for which to
194      *  acquire and return a RequestProcessor
195      * @param context The <code>ServletContext</code> instance
196      *  for this web application
197      *
198      * @exception IllegalStateException if we cannot instantiate a
199      *  RequestProcessor instance
200      */
201     protected RequestProcessor getRequestProcessor(ModuleConfig config,
202                                                    ServletContext context) {
203 
204         String key = Globals.REQUEST_PROCESSOR_KEY + config.getPrefix();
205         RequestProcessor processor =
206             (RequestProcessor) context.getAttribute(key);
207 
208         if (processor == null) {
209             try {
210                 if (log.isDebugEnabled()) {
211                     log.debug("Instantiating RequestProcessor of class " +
212                               config.getControllerConfig().getProcessorClass());
213                 }
214                 ActionServlet servlet = (ActionServlet)
215                 context.getAttribute(Globals.ACTION_SERVLET_KEY);
216                 processor =
217                     (RequestProcessor) RequestUtils.applicationInstance(
218                         config.getControllerConfig().getProcessorClass());
219                 processor.init(servlet, config);
220                 context.setAttribute(key, processor);
221             } catch (Exception e) {
222                 log.error("Cannot instantiate RequestProcessor of class "
223                           + config.getControllerConfig().getProcessorClass(),
224                           e);
225                 throw new IllegalStateException(
226                     "Cannot initialize RequestProcessor of class "
227                         + config.getControllerConfig().getProcessorClass()
228                         + ": "
229                         + e);
230             }
231 
232         }
233         return (processor);
234 
235     }
236 
237 
238 }