View Javadoc

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