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 }