View Javadoc
1   /*
2    * $Id$
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  package org.apache.struts.chain.commands;
22  
23  import org.apache.struts.chain.contexts.ActionContext;
24  import org.apache.struts.config.ActionConfig;
25  import org.apache.struts.config.ExceptionConfig;
26  import org.apache.struts.config.ForwardConfig;
27  import org.apache.struts.config.ModuleConfig;
28  import org.slf4j.Logger;
29  import org.slf4j.LoggerFactory;
30  
31  /**
32   * <p>Invoke the local or global exception handler configured for the
33   * exception class that occurred.</p>
34   *
35   * @version $Rev$ $Date: 2005-11-12 13:01:44 -0500 (Sat, 12 Nov 2005)
36   *          $
37   */
38  public abstract class AbstractExceptionHandler extends ActionCommandBase {
39      // ------------------------------------------------------ Instance Variables
40  
41      /**
42       * The {@code Log} instance for this class.
43       */
44      private final Logger log =
45          LoggerFactory.getLogger(AbstractExceptionHandler.class);
46  
47      // ---------------------------------------------------------- Public Methods
48  
49      /**
50       * <p>Invoke the appropriate <code>Action</code> for this request, and
51       * cache the returned <code>ActionForward</code>.</p>
52       *
53       * @param actionCtx The <code>Context</code> for the current request
54       * @return <code>false</code> if a <code>ForwardConfig</code> is returned,
55       *         else <code>true</code> to complete processing
56       * @throws Exception if thrown by the Action class and not declared by an
57       *                   Exception Handler
58       */
59      @Override
60      protected boolean execute_(ActionContext actionCtx)
61          throws Exception {
62          // Look up the exception that was thrown
63          Exception exception = actionCtx.getException();
64  
65          if (exception == null) {
66              log.warn("No Exception found in ActionContext");
67  
68              return PROCESSING_COMPLETE;
69          }
70  
71          // Look up the local or global exception handler configuration
72          ExceptionConfig exceptionConfig = null;
73          ActionConfig actionConfig = actionCtx.getActionConfig();
74          ModuleConfig moduleConfig = actionCtx.getModuleConfig();
75  
76          if (actionConfig != null) {
77              log.debug("See if actionConfig {} has an exceptionConfig for {}",
78                  actionConfig, exception.getClass().getName());
79  
80              exceptionConfig = actionConfig.findException(exception.getClass());
81          } else if (moduleConfig != null) {
82              log.debug("No action yet, see if moduleConfig {} has an exceptionConfig {}",
83                  moduleConfig, exception.getClass().getName());
84  
85              exceptionConfig = moduleConfig.findException(exception.getClass());
86          }
87  
88          // Handle the exception in the configured manner
89          if (exceptionConfig == null) {
90              log.warn("Unhandled exception", exception);
91              throw exception;
92          }
93  
94          ForwardConfig forwardConfig =
95              handle(actionCtx, exception, exceptionConfig, actionConfig,
96                  moduleConfig);
97  
98          if (forwardConfig != null) {
99              actionCtx.setForwardConfig(forwardConfig);
100 
101             return CONTINUE_PROCESSING;
102         } else {
103             return PROCESSING_COMPLETE;
104         }
105     }
106 
107     // ------------------------------------------------------- Protected Methods
108 
109     /**
110      * <p>Perform the required handling of the specified exception.</p>
111      *
112      * @param context         The <code>Context</code> for this request
113      * @param exception       The exception being handled
114      * @param exceptionConfig The corresponding {@link ExceptionConfig}
115      * @param actionConfig    The {@link ActionConfig} for this request
116      * @param moduleConfig    The {@link ModuleConfig} for this request
117      * @return the <code>ForwardConfig</code> to be processed next (if any),
118      *         or <code>null</code> if processing has been completed
119      * @throws Exception if there are any problems handling the exception
120      */
121     protected abstract ForwardConfig handle(ActionContext context,
122         Exception exception, ExceptionConfig exceptionConfig,
123         ActionConfig actionConfig, ModuleConfig moduleConfig)
124         throws Exception;
125 }