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