View Javadoc

1   /*
2    * $Id: ExceptionCatcher.java 421119 2006-07-12 04:49:11Z wsmoak $
3    *
4    * Copyright 2003-2005 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.struts.chain.commands;
19  
20  import org.apache.commons.chain.Catalog;
21  import org.apache.commons.chain.CatalogFactory;
22  import org.apache.commons.chain.Command;
23  import org.apache.commons.chain.Context;
24  import org.apache.commons.chain.Filter;
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  import org.apache.struts.chain.contexts.ActionContext;
28  
29  /***
30   * <p>Intercept any exception thrown by a subsequent <code>Command</code> in
31   * this processing chain, and fire the configured exception handler chain
32   * after storing the exception that has occurred into the
33   * <code>Context</code>. </p>
34   *
35   * @version $Rev: 421119 $ $Date: 2005-11-12 13:01:44 -0500 (Sat, 12 Nov 2005)
36   *          $
37   */
38  public class ExceptionCatcher extends ActionCommandBase implements Filter {
39      /***
40       * <p> Provide Commons Logging instance for this class. </p>
41       */
42      private static final Log LOG = LogFactory.getLog(ExceptionCatcher.class);
43  
44      // ------------------------------------------------------ Instance Variables
45  
46      /***
47       * <p> Field for CatalogName property. </p>
48       */
49      private String catalogName = null;
50  
51      /***
52       * <p> Field for ExceptionCommand property. </p>
53       */
54      private String exceptionCommand = null;
55  
56      // -------------------------------------------------------------- Properties
57  
58      /***
59       * <p> Return the name of the <code>Catalog</code> in which to perform
60       * lookups, or <code>null</code> for the default <code>Catalog</code>.
61       * </p>
62       *
63       * @return Name of catalog to use, or null
64       */
65      public String getCatalogName() {
66          return (this.catalogName);
67      }
68  
69      /***
70       * <p>Set the name of the <code>Catalog</code> in which to perform
71       * lookups, or <code>null</code> for the default <code>Catalog</code>.</p>
72       *
73       * @param catalogName The new catalog name or <code>null</code>
74       */
75      public void setCatalogName(String catalogName) {
76          this.catalogName = catalogName;
77      }
78  
79      /***
80       * <p> Return the name of the command to be executed if an exception
81       * occurs. </p>
82       *
83       * @return The name of the command to be executed on an exception
84       */
85      public String getExceptionCommand() {
86          return (this.exceptionCommand);
87      }
88  
89      /***
90       * <p>Set the name of the command to be executed if an exception
91       * occurs.</p>
92       *
93       * @param exceptionCommand The name of the chain to be executed
94       */
95      public void setExceptionCommand(String exceptionCommand) {
96          this.exceptionCommand = exceptionCommand;
97      }
98  
99      // ---------------------------------------------------------- Public Methods
100 
101     /***
102      * <p>Clear any existing stored exception and pass the
103      * <code>context</code> on to the remainder of the current chain.</p>
104      *
105      * @param actionCtx The <code>Context</code> for the current request
106      * @return <code>false</code> so that processing continues
107      * @throws Exception On any error
108      */
109     public boolean execute(ActionContext actionCtx)
110         throws Exception {
111         actionCtx.setException(null);
112 
113         return (false);
114     }
115 
116     /***
117      * <p>If an exception was thrown by a subsequent <code>Command</code>,
118      * pass it on to the specified exception handling chain.  Otherwise, do
119      * nothing.</p>
120      *
121      * @param context   The {@link Context} to be processed by this {@link
122      *                  Filter}
123      * @param exception The <code>Exception</code> (if any) that was thrown by
124      *                  the last {@link Command} that was executed; otherwise
125      *                  <code>null</code>
126      * @return TRUE if post processing an exception occurred and the exception
127      *         processing chain invoked
128      * @throws IllegalStateException If exception throws exception
129      */
130     public boolean postprocess(Context context, Exception exception) {
131         // Do nothing if there was no exception thrown
132         if (exception == null) {
133             return (false);
134         }
135 
136         // Stash the exception in the specified context attribute
137         if (LOG.isDebugEnabled()) {
138             LOG.debug("Attempting to handle a thrown exception");
139         }
140 
141         ActionContext actionCtx = (ActionContext) context;
142 
143         actionCtx.setException(exception);
144 
145         // Execute the specified command
146         try {
147             Command command = lookupExceptionCommand();
148 
149             if (command == null) {
150                 LOG.error("Cannot find exceptionCommand '" + exceptionCommand
151                     + "'");
152                 throw new IllegalStateException(
153                     "Cannot find exceptionCommand '" + exceptionCommand + "'");
154             }
155 
156             if (LOG.isTraceEnabled()) {
157                 LOG.trace("Calling exceptionCommand '" + exceptionCommand + "'");
158             }
159 
160             command.execute(context);
161         } catch (Exception e) {
162             LOG.warn("Exception from exceptionCommand '" + exceptionCommand
163                 + "'", e);
164             throw new IllegalStateException("Exception chain threw exception");
165         }
166 
167         return (true);
168     }
169 
170     /***
171      * <p> Return the command to be executed if an exception occurs. </p>
172      *
173      * @return The command to be executed if an exception occurs
174      * @throws IllegalArgumentException If catalog cannot be found
175      * @throws IllegalStateException    If command property is not specified
176      */
177     protected Command lookupExceptionCommand() {
178         String catalogName = getCatalogName();
179         Catalog catalog;
180 
181         if (catalogName == null) {
182             catalog = CatalogFactory.getInstance().getCatalog();
183 
184             if (catalog == null) {
185                 LOG.error("Cannot find default catalog");
186                 throw new IllegalArgumentException(
187                     "Cannot find default catalog");
188             }
189         } else {
190             catalog = CatalogFactory.getInstance().getCatalog(catalogName);
191 
192             if (catalog == null) {
193                 LOG.error("Cannot find catalog '" + catalogName + "'");
194                 throw new IllegalArgumentException("Cannot find catalog '"
195                     + catalogName + "'");
196             }
197         }
198 
199         String exceptionCommand = getExceptionCommand();
200 
201         if (exceptionCommand == null) {
202             LOG.error("No exceptionCommand property specified");
203             throw new IllegalStateException(
204                 "No exceptionCommand property specfied");
205         }
206 
207         return catalog.getCommand(exceptionCommand);
208     }
209 }