View Javadoc

1   /*
2    * $Id: ConfigRuleSet.java 421119 2006-07-12 04:49:11Z wsmoak $
3    *
4    * Copyright 2000-2004 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
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      // --------------------------------------------------------- Public Methods
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         // PluginConfig does not extend BaseConfig, at least for now.
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         // Identify the name of the class to instantiate
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         // Instantiate the new object and return it
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         // Identify the name of the class to instantiate
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         // Instantiate the new object and return it
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         // Identify the name of the class to instantiate
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         // Instantiate the new object and return it
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         // Identify the name of the class to instantiate
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         // Instantiate the new object and return it
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 }