1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.struts.config;
22
23 import java.lang.reflect.InvocationTargetException;
24
25 /**
26 * <p>A JavaBean representing the configuration information of an
27 * <code><exception></code> element from a Struts configuration
28 * file.</p>
29 *
30 * @version $Rev: 471754 $ $Date: 2005-08-06 18:03:30 -0400 (Sat, 06 Aug 2005)
31 * $
32 * @since Struts 1.1
33 */
34 public class ExceptionConfig extends BaseConfig {
35
36
37 /**
38 * The servlet context attribute under which the message resources bundle
39 * to be used for this exception is located. If not set, the default
40 * message resources for the current module is assumed.
41 */
42 protected String bundle = null;
43
44 /**
45 * The type of the ExceptionConfig that this object should inherit
46 * properties from.
47 */
48 protected String inherit = null;
49
50 /**
51 * Have the inheritance values for this class been applied?
52 */
53 protected boolean extensionProcessed = false;
54
55 /**
56 * The fully qualified Java class name of the exception handler class
57 * which should be instantiated to handle this exception.
58 */
59 protected String handler = "org.apache.struts.action.ExceptionHandler";
60
61 /**
62 * The message resources key specifying the error message associated with
63 * this exception.
64 */
65 protected String key = null;
66
67 /**
68 * The module-relative path of the resource to forward to if this
69 * exception occurs during an <code>Action</code>.
70 */
71 protected String path = null;
72
73 /**
74 * The scope in which we should expose the ActionMessage for this
75 * exception handler.
76 */
77 protected String scope = "request";
78
79 /**
80 * The fully qualified Java class name of the exception that is to be
81 * handled by this handler.
82 */
83 protected String type = null;
84
85 public String getBundle() {
86 return (this.bundle);
87 }
88
89 public void setBundle(String bundle) {
90 if (configured) {
91 throw new IllegalStateException("Configuration is frozen");
92 }
93
94 this.bundle = bundle;
95 }
96
97 public String getExtends() {
98 return (this.inherit);
99 }
100
101 public void setExtends(String inherit) {
102 if (configured) {
103 throw new IllegalStateException("Configuration is frozen");
104 }
105
106 this.inherit = inherit;
107 }
108
109 public boolean isExtensionProcessed() {
110 return extensionProcessed;
111 }
112
113 public String getHandler() {
114 return (this.handler);
115 }
116
117 public void setHandler(String handler) {
118 if (configured) {
119 throw new IllegalStateException("Configuration is frozen");
120 }
121
122 this.handler = handler;
123 }
124
125 public String getKey() {
126 return (this.key);
127 }
128
129 public void setKey(String key) {
130 if (configured) {
131 throw new IllegalStateException("Configuration is frozen");
132 }
133
134 this.key = key;
135 }
136
137 public String getPath() {
138 return (this.path);
139 }
140
141 public void setPath(String path) {
142 if (configured) {
143 throw new IllegalStateException("Configuration is frozen");
144 }
145
146 this.path = path;
147 }
148
149 public String getScope() {
150 return (this.scope);
151 }
152
153 public void setScope(String scope) {
154 if (configured) {
155 throw new IllegalStateException("Configuration is frozen");
156 }
157
158 this.scope = scope;
159 }
160
161 public String getType() {
162 return (this.type);
163 }
164
165 public void setType(String type) {
166 if (configured) {
167 throw new IllegalStateException("Configuration is frozen");
168 }
169
170 this.type = type;
171 }
172
173
174
175 /**
176 * <p>Traces the hierarchy of this object to check if any of the ancestors
177 * are extending this instance.</p>
178 *
179 * @param moduleConfig The {@link ModuleConfig} that this config is from.
180 * @param actionConfig The {@link ActionConfig} that this config is from,
181 * if applicable. This parameter must be null if this
182 * is a global handler.
183 * @return true if circular inheritance was detected.
184 */
185 protected boolean checkCircularInheritance(ModuleConfig moduleConfig,
186 ActionConfig actionConfig) {
187 String ancestorType = getExtends();
188
189 if (ancestorType == null) {
190 return false;
191 }
192
193
194 ExceptionConfig ancestor = null;
195
196
197 if (actionConfig != null) {
198 ancestor = actionConfig.findExceptionConfig(ancestorType);
199
200
201 if (ancestor == this) {
202 ancestor = null;
203 }
204 }
205
206
207 if (ancestor == null) {
208 ancestor = moduleConfig.findExceptionConfig(ancestorType);
209
210 if (ancestor != null) {
211
212
213
214 actionConfig = null;
215 }
216 }
217
218 while (ancestor != null) {
219
220 if (ancestor == this) {
221 return true;
222 }
223
224
225 ancestorType = ancestor.getExtends();
226
227
228 if (ancestor.getType().equals(ancestorType)) {
229
230
231
232 if (actionConfig == null) {
233 return false;
234 } else {
235
236
237 actionConfig = null;
238 }
239 }
240
241 ancestor = null;
242
243
244 if (actionConfig != null) {
245 ancestor = actionConfig.findExceptionConfig(ancestorType);
246 }
247
248
249 if (ancestor == null) {
250 ancestor = moduleConfig.findExceptionConfig(ancestorType);
251
252 if (ancestor != null) {
253
254 actionConfig = null;
255 }
256 }
257 }
258
259 return false;
260 }
261
262
263
264 /**
265 * <p>Inherit values that have not been overridden from the provided
266 * config object. Subclasses overriding this method should verify that
267 * the given parameter is of a class that contains a property it is trying
268 * to inherit:</p>
269 *
270 * <pre>
271 * if (config instanceof MyCustomConfig) {
272 * MyCustomConfig myConfig =
273 * (MyCustomConfig) config;
274 *
275 * if (getMyCustomProp() == null) {
276 * setMyCustomProp(myConfig.getMyCustomProp());
277 * }
278 * }
279 * </pre>
280 *
281 * <p>If the given <code>config</code> is extending another object, those
282 * extensions should be resolved before it's used as a parameter to this
283 * method.</p>
284 *
285 * @param config The object that this instance will be inheriting its
286 * values from.
287 * @see #processExtends(ModuleConfig, ActionConfig)
288 */
289 public void inheritFrom(ExceptionConfig config)
290 throws ClassNotFoundException, IllegalAccessException,
291 InstantiationException, InvocationTargetException {
292 if (configured) {
293 throw new IllegalStateException("Configuration is frozen");
294 }
295
296
297 if (getBundle() == null) {
298 setBundle(config.getBundle());
299 }
300
301 if (getHandler().equals("org.apache.struts.action.ExceptionHandler")) {
302 setHandler(config.getHandler());
303 }
304
305 if (getKey() == null) {
306 setKey(config.getKey());
307 }
308
309 if (getPath() == null) {
310 setPath(config.getPath());
311 }
312
313 if (getScope().equals("request")) {
314 setScope(config.getScope());
315 }
316
317 if (getType() == null) {
318 setType(config.getType());
319 }
320
321 inheritProperties(config);
322 }
323
324 /**
325 * <p>Inherit configuration information from the ExceptionConfig that this
326 * instance is extending. This method verifies that any exception config
327 * object that it inherits from has also had its processExtends() method
328 * called.</p>
329 *
330 * @param moduleConfig The {@link ModuleConfig} that this config is from.
331 * @param actionConfig The {@link ActionConfig} that this config is from,
332 * if applicable. This must be null for global
333 * forwards.
334 * @see #inheritFrom(ExceptionConfig)
335 */
336 public void processExtends(ModuleConfig moduleConfig,
337 ActionConfig actionConfig)
338 throws ClassNotFoundException, IllegalAccessException,
339 InstantiationException, InvocationTargetException {
340 if (configured) {
341 throw new IllegalStateException("Configuration is frozen");
342 }
343
344 String ancestorType = getExtends();
345
346 if ((!extensionProcessed) && (ancestorType != null)) {
347 ExceptionConfig baseConfig = null;
348
349
350 boolean checkActionConfig =
351 (this != moduleConfig.findExceptionConfig(getType()));
352
353
354 checkActionConfig &= (actionConfig != null);
355
356
357
358
359 checkActionConfig &= !ancestorType.equals(getType());
360
361
362 if (checkActionConfig) {
363 baseConfig = actionConfig.findExceptionConfig(ancestorType);
364 }
365
366
367 if (baseConfig == null) {
368 baseConfig = moduleConfig.findExceptionConfig(ancestorType);
369 }
370
371 if (baseConfig == null) {
372 throw new NullPointerException("Unable to find "
373 + "handler for '" + ancestorType + "' to extend.");
374 }
375
376
377
378 if (checkCircularInheritance(moduleConfig, actionConfig)) {
379 throw new IllegalArgumentException(
380 "Circular inheritance detected for forward " + getType());
381 }
382
383 if (!baseConfig.isExtensionProcessed()) {
384 baseConfig.processExtends(moduleConfig, actionConfig);
385 }
386
387
388 inheritFrom(baseConfig);
389 }
390
391 extensionProcessed = true;
392 }
393
394 /**
395 * Return a String representation of this object.
396 */
397 public String toString() {
398 StringBuffer sb = new StringBuffer("ExceptionConfig[");
399
400 sb.append("type=");
401 sb.append(this.type);
402
403 if (this.bundle != null) {
404 sb.append(",bundle=");
405 sb.append(this.bundle);
406 }
407
408 if (this.inherit != null) {
409 sb.append(",extends=");
410 sb.append(this.inherit);
411 }
412
413 sb.append(",handler=");
414 sb.append(this.handler);
415 sb.append(",key=");
416 sb.append(this.key);
417 sb.append(",path=");
418 sb.append(this.path);
419 sb.append(",scope=");
420 sb.append(this.scope);
421 sb.append("]");
422
423 return (sb.toString());
424 }
425 }