001: /*
002: * $Id: ExceptionCatcher.java 471754 2006-11-06 14:55:09Z husted $
003: *
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021: package org.apache.struts.chain.commands;
022:
023: import org.apache.commons.chain.Catalog;
024: import org.apache.commons.chain.CatalogFactory;
025: import org.apache.commons.chain.Command;
026: import org.apache.commons.chain.Context;
027: import org.apache.commons.chain.Filter;
028: import org.apache.commons.logging.Log;
029: import org.apache.commons.logging.LogFactory;
030: import org.apache.struts.chain.contexts.ActionContext;
031:
032: /**
033: * <p>Intercept any exception thrown by a subsequent <code>Command</code> in
034: * this processing chain, and fire the configured exception handler chain
035: * after storing the exception that has occurred into the
036: * <code>Context</code>. </p>
037: *
038: * @version $Rev: 471754 $ $Date: 2005-11-12 13:01:44 -0500 (Sat, 12 Nov 2005)
039: * $
040: */
041: public class ExceptionCatcher extends ActionCommandBase implements
042: Filter {
043: /**
044: * <p> Provide Commons Logging instance for this class. </p>
045: */
046: private static final Log LOG = LogFactory
047: .getLog(ExceptionCatcher.class);
048:
049: // ------------------------------------------------------ Instance Variables
050:
051: /**
052: * <p> Field for CatalogName property. </p>
053: */
054: private String catalogName = null;
055:
056: /**
057: * <p> Field for ExceptionCommand property. </p>
058: */
059: private String exceptionCommand = null;
060:
061: // -------------------------------------------------------------- Properties
062:
063: /**
064: * <p> Return the name of the <code>Catalog</code> in which to perform
065: * lookups, or <code>null</code> for the default <code>Catalog</code>.
066: * </p>
067: *
068: * @return Name of catalog to use, or null
069: */
070: public String getCatalogName() {
071: return (this .catalogName);
072: }
073:
074: /**
075: * <p>Set the name of the <code>Catalog</code> in which to perform
076: * lookups, or <code>null</code> for the default <code>Catalog</code>.</p>
077: *
078: * @param catalogName The new catalog name or <code>null</code>
079: */
080: public void setCatalogName(String catalogName) {
081: this .catalogName = catalogName;
082: }
083:
084: /**
085: * <p> Return the name of the command to be executed if an exception
086: * occurs. </p>
087: *
088: * @return The name of the command to be executed on an exception
089: */
090: public String getExceptionCommand() {
091: return (this .exceptionCommand);
092: }
093:
094: /**
095: * <p>Set the name of the command to be executed if an exception
096: * occurs.</p>
097: *
098: * @param exceptionCommand The name of the chain to be executed
099: */
100: public void setExceptionCommand(String exceptionCommand) {
101: this .exceptionCommand = exceptionCommand;
102: }
103:
104: // ---------------------------------------------------------- Public Methods
105:
106: /**
107: * <p>Clear any existing stored exception and pass the
108: * <code>context</code> on to the remainder of the current chain.</p>
109: *
110: * @param actionCtx The <code>Context</code> for the current request
111: * @return <code>false</code> so that processing continues
112: * @throws Exception On any error
113: */
114: public boolean execute(ActionContext actionCtx) throws Exception {
115: actionCtx.setException(null);
116:
117: return (false);
118: }
119:
120: /**
121: * <p>If an exception was thrown by a subsequent <code>Command</code>,
122: * pass it on to the specified exception handling chain. Otherwise, do
123: * nothing.</p>
124: *
125: * @param context The {@link Context} to be processed by this {@link
126: * Filter}
127: * @param exception The <code>Exception</code> (if any) that was thrown by
128: * the last {@link Command} that was executed; otherwise
129: * <code>null</code>
130: * @return TRUE if post processing an exception occurred and the exception
131: * processing chain invoked
132: * @throws IllegalStateException If exception throws exception
133: */
134: public boolean postprocess(Context context, Exception exception) {
135: // Do nothing if there was no exception thrown
136: if (exception == null) {
137: return (false);
138: }
139:
140: // Stash the exception in the specified context attribute
141: if (LOG.isDebugEnabled()) {
142: LOG.debug("Attempting to handle a thrown exception");
143: }
144:
145: ActionContext actionCtx = (ActionContext) context;
146:
147: actionCtx.setException(exception);
148:
149: // Execute the specified command
150: try {
151: Command command = lookupExceptionCommand();
152:
153: if (command == null) {
154: LOG.error("Cannot find exceptionCommand '"
155: + exceptionCommand + "'");
156: throw new IllegalStateException(
157: "Cannot find exceptionCommand '"
158: + exceptionCommand + "'");
159: }
160:
161: if (LOG.isTraceEnabled()) {
162: LOG.trace("Calling exceptionCommand '"
163: + exceptionCommand + "'");
164: }
165:
166: command.execute(context);
167: } catch (Exception e) {
168: LOG.warn("Exception from exceptionCommand '"
169: + exceptionCommand + "'", e);
170: throw new IllegalStateException(
171: "Exception chain threw exception");
172: }
173:
174: return (true);
175: }
176:
177: /**
178: * <p> Return the command to be executed if an exception occurs. </p>
179: *
180: * @return The command to be executed if an exception occurs
181: * @throws IllegalArgumentException If catalog cannot be found
182: * @throws IllegalStateException If command property is not specified
183: */
184: protected Command lookupExceptionCommand() {
185: String catalogName = getCatalogName();
186: Catalog catalog;
187:
188: if (catalogName == null) {
189: catalog = CatalogFactory.getInstance().getCatalog();
190:
191: if (catalog == null) {
192: LOG.error("Cannot find default catalog");
193: throw new IllegalArgumentException(
194: "Cannot find default catalog");
195: }
196: } else {
197: catalog = CatalogFactory.getInstance().getCatalog(
198: catalogName);
199:
200: if (catalog == null) {
201: LOG.error("Cannot find catalog '" + catalogName + "'");
202: throw new IllegalArgumentException(
203: "Cannot find catalog '" + catalogName + "'");
204: }
205: }
206:
207: String exceptionCommand = getExceptionCommand();
208:
209: if (exceptionCommand == null) {
210: LOG.error("No exceptionCommand property specified");
211: throw new IllegalStateException(
212: "No exceptionCommand property specfied");
213: }
214:
215: return catalog.getCommand(exceptionCommand);
216: }
217: }
|