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 org.apache.commons.digester.AbstractObjectCreationFactory;
21 import org.apache.commons.digester.Digester;
22 import org.apache.commons.digester.Rule;
23 import org.apache.commons.digester.RuleSetBase;
24 import org.apache.commons.digester.SetPropertyRule;
25 import org.apache.struts.util.RequestUtils;
26 import org.xml.sax.Attributes;
27
28 /***
29 * <p>The set of Digester rules required to parse a Struts configuration file
30 * (<code>struts-config.xml</code>).</p>
31 *
32 * @version $Rev: 421119 $ $Date: 2005-08-16 15:53:27 -0400 (Tue, 16 Aug 2005)
33 * $
34 * @since Struts 1.1
35 */
36 public class ConfigRuleSet extends RuleSetBase {
37
38
39 /***
40 * <p>Add the set of Rule instances defined in this RuleSet to the
41 * specified <code>Digester</code> instance, associating them with our
42 * namespace URI (if any). This method should only be called by a
43 * Digester instance. These rules assume that an instance of
44 * <code>org.apache.struts.config.ModuleConfig</code> is pushed onto the
45 * evaluation stack before parsing begins.</p>
46 *
47 * @param digester Digester instance to which the new Rule instances
48 * should be added.
49 */
50 public void addRuleInstances(Digester digester) {
51 ClassLoader cl = digester.getClassLoader();
52
53 digester.addRule("struts-config/action-mappings",
54 new SetActionMappingClassRule());
55
56 digester.addFactoryCreate("struts-config/action-mappings/action",
57 new ActionMappingFactory(cl));
58 digester.addSetProperties("struts-config/action-mappings/action");
59 digester.addSetNext("struts-config/action-mappings/action",
60 "addActionConfig", "org.apache.struts.config.ActionConfig");
61
62 digester.addRule("struts-config/action-mappings/action/set-property",
63 new BaseConfigSetPropertyRule());
64
65 digester.addObjectCreate("struts-config/action-mappings/action/exception",
66 "org.apache.struts.config.ExceptionConfig", "className");
67 digester.addSetProperties(
68 "struts-config/action-mappings/action/exception");
69 digester.addSetNext("struts-config/action-mappings/action/exception",
70 "addExceptionConfig", "org.apache.struts.config.ExceptionConfig");
71
72 digester.addRule("struts-config/action-mappings/action/exception/set-property",
73 new BaseConfigSetPropertyRule());
74
75 digester.addFactoryCreate("struts-config/action-mappings/action/forward",
76 new ActionForwardFactory(cl));
77 digester.addSetProperties(
78 "struts-config/action-mappings/action/forward");
79 digester.addSetNext("struts-config/action-mappings/action/forward",
80 "addForwardConfig", "org.apache.struts.config.ForwardConfig");
81
82 digester.addRule("struts-config/action-mappings/action/forward/set-property",
83 new BaseConfigSetPropertyRule());
84
85 digester.addObjectCreate("struts-config/controller",
86 "org.apache.struts.config.ControllerConfig", "className");
87 digester.addSetProperties("struts-config/controller");
88 digester.addSetNext("struts-config/controller", "setControllerConfig",
89 "org.apache.struts.config.ControllerConfig");
90
91 digester.addRule("struts-config/controller/set-property",
92 new BaseConfigSetPropertyRule());
93
94 digester.addRule("struts-config/form-beans",
95 new SetActionFormBeanClassRule());
96
97 digester.addFactoryCreate("struts-config/form-beans/form-bean",
98 new ActionFormBeanFactory(cl));
99 digester.addSetProperties("struts-config/form-beans/form-bean");
100 digester.addSetNext("struts-config/form-beans/form-bean",
101 "addFormBeanConfig", "org.apache.struts.config.FormBeanConfig");
102
103 digester.addObjectCreate("struts-config/form-beans/form-bean/form-property",
104 "org.apache.struts.config.FormPropertyConfig", "className");
105 digester.addSetProperties(
106 "struts-config/form-beans/form-bean/form-property");
107 digester.addSetNext("struts-config/form-beans/form-bean/form-property",
108 "addFormPropertyConfig",
109 "org.apache.struts.config.FormPropertyConfig");
110
111 digester.addRule("struts-config/form-beans/form-bean/form-property/set-property",
112 new BaseConfigSetPropertyRule());
113
114 digester.addRule("struts-config/form-beans/form-bean/set-property",
115 new BaseConfigSetPropertyRule());
116
117 digester.addObjectCreate("struts-config/global-exceptions/exception",
118 "org.apache.struts.config.ExceptionConfig", "className");
119 digester.addSetProperties("struts-config/global-exceptions/exception");
120 digester.addSetNext("struts-config/global-exceptions/exception",
121 "addExceptionConfig", "org.apache.struts.config.ExceptionConfig");
122
123 digester.addRule("struts-config/global-exceptions/exception/set-property",
124 new BaseConfigSetPropertyRule());
125
126 digester.addRule("struts-config/global-forwards",
127 new SetActionForwardClassRule());
128
129 digester.addFactoryCreate("struts-config/global-forwards/forward",
130 new GlobalForwardFactory(cl));
131 digester.addSetProperties("struts-config/global-forwards/forward");
132 digester.addSetNext("struts-config/global-forwards/forward",
133 "addForwardConfig", "org.apache.struts.config.ForwardConfig");
134
135 digester.addRule("struts-config/global-forwards/forward/set-property",
136 new BaseConfigSetPropertyRule());
137
138 digester.addObjectCreate("struts-config/message-resources",
139 "org.apache.struts.config.MessageResourcesConfig", "className");
140 digester.addSetProperties("struts-config/message-resources");
141 digester.addSetNext("struts-config/message-resources",
142 "addMessageResourcesConfig",
143 "org.apache.struts.config.MessageResourcesConfig");
144
145 digester.addRule("struts-config/message-resources/set-property",
146 new BaseConfigSetPropertyRule());
147
148 digester.addObjectCreate("struts-config/plug-in",
149 "org.apache.struts.config.PlugInConfig");
150 digester.addSetProperties("struts-config/plug-in");
151 digester.addSetNext("struts-config/plug-in", "addPlugInConfig",
152 "org.apache.struts.config.PlugInConfig");
153
154 digester.addRule("struts-config/plug-in/set-property",
155 new PlugInSetPropertyRule());
156
157
158 }
159 }
160
161
162 /***
163 * <p> Class that records the name and value of a configuration property to be
164 * used in configuring a <code>PlugIn</code> instance when instantiated. </p>
165 */
166 final class PlugInSetPropertyRule extends Rule {
167 public PlugInSetPropertyRule() {
168 super();
169 }
170
171 public void begin(String namespace, String names, Attributes attributes)
172 throws Exception {
173 PlugInConfig plugInConfig = (PlugInConfig) digester.peek();
174
175 plugInConfig.addProperty(attributes.getValue("property"),
176 attributes.getValue("value"));
177 }
178 }
179
180
181 /***
182 * <p> Class that sets the name of the class to use when creating action form
183 * bean instances. The value is set on the object on the top of the stack,
184 * which must be a <code>org.apache.struts.config.ModuleConfig</code>. </p>
185 */
186 final class SetActionFormBeanClassRule extends Rule {
187 public SetActionFormBeanClassRule() {
188 super();
189 }
190
191 public void begin(String namespace, String name, Attributes attributes)
192 throws Exception {
193 String className = attributes.getValue("type");
194
195 if (className != null) {
196 ModuleConfig mc = (ModuleConfig) digester.peek();
197
198 mc.setActionFormBeanClass(className);
199 }
200 }
201 }
202
203
204 /***
205 * <p> A variant of the standard Digester <code>SetPropertyRule</code>. If
206 * the element being processed has a "key" attribute, then the value will be
207 * used to call <code>setProperty(key,value)</code> on the object on top of
208 * the stack, which will be assumed to be of type <code>ActionConfig</code>.
209 * Otherwise, the standard <code>SetPropertyRule</code> behavior is invoked,
210 * and the value will be used to set a bean property on the object on top of
211 * the Digester stack. In that case, the element being processed is assumed to
212 * have attributes "property" and "value". </p>
213 */
214 final class BaseConfigSetPropertyRule extends SetPropertyRule {
215 public BaseConfigSetPropertyRule() {
216 super("property", "value");
217 }
218
219 public void begin(Attributes attributes)
220 throws Exception {
221 if (attributes.getIndex("key") == -1) {
222 super.begin(attributes);
223
224 return;
225 }
226
227 if (attributes.getIndex("property") != -1) {
228 throw new IllegalArgumentException(
229 "<set-property> accepts only one of 'key' or 'property' attributes.");
230 }
231
232 Object topOfStack = digester.peek();
233
234 if (topOfStack instanceof BaseConfig) {
235 BaseConfig config = (BaseConfig) topOfStack;
236
237 config.setProperty(attributes.getValue("key"),
238 attributes.getValue("value"));
239 } else {
240 throw new IllegalArgumentException(
241 "'key' attribute of <set-property> only applicable to subclasses of BaseConfig; "
242 + "object on top of stack is " + topOfStack + " [key: "
243 + attributes.getValue("key") + ", value: "
244 + attributes.getValue("value") + "]");
245 }
246 }
247 }
248
249
250 /***
251 * <p> An object creation factory which creates action form bean instances,
252 * taking into account the default class name, which may have been specified
253 * on the parent element and which is made available through the object on the
254 * top of the stack, which must be a <code>org.apache.struts.config.ModuleConfig</code>.
255 * </p>
256 */
257 final class ActionFormBeanFactory extends AbstractObjectCreationFactory {
258 private ClassLoader cl;
259
260 public ActionFormBeanFactory(ClassLoader cl) {
261 super();
262 this.cl = cl;
263 }
264
265 public Object createObject(Attributes attributes) {
266
267 String className = attributes.getValue("className");
268
269 if (className == null) {
270 ModuleConfig mc = (ModuleConfig) digester.peek();
271
272 className = mc.getActionFormBeanClass();
273 }
274
275
276 Object actionFormBean = null;
277
278 try {
279 actionFormBean = RequestUtils.applicationInstance(className, cl);
280 } catch (Exception e) {
281 digester.getLogger().error("ActionFormBeanFactory.createObject: ", e);
282 }
283
284 return actionFormBean;
285 }
286 }
287
288
289 /***
290 * <p> Class that sets the name of the class to use when creating action
291 * mapping instances. The value is set on the object on the top of the stack,
292 * which must be a <code>org.apache.struts.config.ModuleConfig</code>. </p>
293 */
294 final class SetActionMappingClassRule extends Rule {
295 public SetActionMappingClassRule() {
296 super();
297 }
298
299 public void begin(String namespace, String name, Attributes attributes)
300 throws Exception {
301 String className = attributes.getValue("type");
302
303 if (className != null) {
304 ModuleConfig mc = (ModuleConfig) digester.peek();
305
306 mc.setActionMappingClass(className);
307 }
308 }
309 }
310
311
312 /***
313 * <p> An object creation factory which creates action mapping instances,
314 * taking into account the default class name, which may have been specified
315 * on the parent element and which is made available through the object on the
316 * top of the stack, which must be a <code>org.apache.struts.config.ModuleConfig</code>.
317 * </p>
318 */
319 final class ActionMappingFactory extends AbstractObjectCreationFactory {
320 private ClassLoader cl;
321
322 public ActionMappingFactory(ClassLoader cl) {
323 super();
324 this.cl = cl;
325 }
326
327 public Object createObject(Attributes attributes) {
328
329 String className = attributes.getValue("className");
330
331 if (className == null) {
332 ModuleConfig mc = (ModuleConfig) digester.peek();
333
334 className = mc.getActionMappingClass();
335 }
336
337
338 Object actionMapping = null;
339
340 try {
341 actionMapping = RequestUtils.applicationInstance(className, cl);
342 } catch (Exception e) {
343 digester.getLogger().error("ActionMappingFactory.createObject: ", e);
344 }
345
346 return actionMapping;
347 }
348 }
349
350
351 /***
352 * <p> Class that sets the name of the class to use when creating global
353 * forward instances. The value is set on the object on the top of the stack,
354 * which must be a <code>org.apache.struts.config.ModuleConfig</code>. </p>
355 */
356 final class SetActionForwardClassRule extends Rule {
357 public SetActionForwardClassRule() {
358 super();
359 }
360
361 public void begin(String namespace, String name, Attributes attributes)
362 throws Exception {
363 String className = attributes.getValue("type");
364
365 if (className != null) {
366 ModuleConfig mc = (ModuleConfig) digester.peek();
367
368 mc.setActionForwardClass(className);
369 }
370 }
371 }
372
373
374 /***
375 * <p> An object creation factory which creates global forward instances,
376 * taking into account the default class name, which may have been specified
377 * on the parent element and which is made available through the object on the
378 * top of the stack, which must be a <code>org.apache.struts.config.ModuleConfig</code>.
379 * </p>
380 */
381 final class GlobalForwardFactory extends AbstractObjectCreationFactory {
382 private ClassLoader cl;
383
384 public GlobalForwardFactory(ClassLoader cl) {
385 super();
386 this.cl = cl;
387 }
388
389 public Object createObject(Attributes attributes) {
390
391 String className = attributes.getValue("className");
392
393 if (className == null) {
394 ModuleConfig mc = (ModuleConfig) digester.peek();
395
396 className = mc.getActionForwardClass();
397 }
398
399
400 Object globalForward = null;
401
402 try {
403 globalForward = RequestUtils.applicationInstance(className, cl);
404 } catch (Exception e) {
405 digester.getLogger().error("GlobalForwardFactory.createObject: ", e);
406 }
407
408 return globalForward;
409 }
410 }
411
412
413 /***
414 * <p> An object creation factory which creates action forward instances,
415 * taking into account the default class name, which may have been specified
416 * on the parent element and which is made available through the object on the
417 * top of the stack, which must be a <code>org.apache.struts.config.ModuleConfig</code>.
418 * </p>
419 */
420 final class ActionForwardFactory extends AbstractObjectCreationFactory {
421 private ClassLoader cl;
422
423 public ActionForwardFactory(ClassLoader cl) {
424 super();
425 this.cl = cl;
426 }
427
428 public Object createObject(Attributes attributes) {
429
430 String className = attributes.getValue("className");
431
432 if (className == null) {
433 ModuleConfig mc = (ModuleConfig) digester.peek(1);
434
435 className = mc.getActionForwardClass();
436 }
437
438
439 Object actionForward = null;
440
441 try {
442 actionForward = RequestUtils.applicationInstance(className, cl);
443 } catch (Exception e) {
444 digester.getLogger().error("ActionForwardFactory.createObject: ", e);
445 }
446
447 return actionForward;
448 }
449 }