View Javadoc

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