001: /*
002: * $Id: ConfigRuleSet.java 471754 2006-11-06 14:55:09Z husted $
003: *
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021: package org.apache.struts.config;
022:
023: import org.apache.commons.digester.AbstractObjectCreationFactory;
024: import org.apache.commons.digester.Digester;
025: import org.apache.commons.digester.Rule;
026: import org.apache.commons.digester.RuleSetBase;
027: import org.apache.commons.digester.SetPropertyRule;
028: import org.apache.struts.util.RequestUtils;
029: import org.xml.sax.Attributes;
030:
031: /**
032: * <p>The set of Digester rules required to parse a Struts configuration file
033: * (<code>struts-config.xml</code>).</p>
034: *
035: * @version $Rev: 471754 $ $Date: 2005-08-16 15:53:27 -0400 (Tue, 16 Aug 2005)
036: * $
037: * @since Struts 1.1
038: */
039: public class ConfigRuleSet extends RuleSetBase {
040: // --------------------------------------------------------- Public Methods
041:
042: /**
043: * <p>Add the set of Rule instances defined in this RuleSet to the
044: * specified <code>Digester</code> instance, associating them with our
045: * namespace URI (if any). This method should only be called by a
046: * Digester instance. These rules assume that an instance of
047: * <code>org.apache.struts.config.ModuleConfig</code> is pushed onto the
048: * evaluation stack before parsing begins.</p>
049: *
050: * @param digester Digester instance to which the new Rule instances
051: * should be added.
052: */
053: public void addRuleInstances(Digester digester) {
054: ClassLoader cl = digester.getClassLoader();
055:
056: digester.addRule("struts-config/action-mappings",
057: new SetActionMappingClassRule());
058:
059: digester.addFactoryCreate(
060: "struts-config/action-mappings/action",
061: new ActionMappingFactory(cl));
062: digester
063: .addSetProperties("struts-config/action-mappings/action");
064: digester.addSetNext("struts-config/action-mappings/action",
065: "addActionConfig",
066: "org.apache.struts.config.ActionConfig");
067:
068: digester.addRule(
069: "struts-config/action-mappings/action/set-property",
070: new BaseConfigSetPropertyRule());
071:
072: digester
073: .addObjectCreate(
074: "struts-config/action-mappings/action/exception",
075: "org.apache.struts.config.ExceptionConfig",
076: "className");
077: digester
078: .addSetProperties("struts-config/action-mappings/action/exception");
079: digester.addSetNext(
080: "struts-config/action-mappings/action/exception",
081: "addExceptionConfig",
082: "org.apache.struts.config.ExceptionConfig");
083:
084: digester
085: .addRule(
086: "struts-config/action-mappings/action/exception/set-property",
087: new BaseConfigSetPropertyRule());
088:
089: digester.addFactoryCreate(
090: "struts-config/action-mappings/action/forward",
091: new ActionForwardFactory(cl));
092: digester
093: .addSetProperties("struts-config/action-mappings/action/forward");
094: digester.addSetNext(
095: "struts-config/action-mappings/action/forward",
096: "addForwardConfig",
097: "org.apache.struts.config.ForwardConfig");
098:
099: digester
100: .addRule(
101: "struts-config/action-mappings/action/forward/set-property",
102: new BaseConfigSetPropertyRule());
103:
104: digester.addObjectCreate("struts-config/controller",
105: "org.apache.struts.config.ControllerConfig",
106: "className");
107: digester.addSetProperties("struts-config/controller");
108: digester.addSetNext("struts-config/controller",
109: "setControllerConfig",
110: "org.apache.struts.config.ControllerConfig");
111:
112: digester.addRule("struts-config/controller/set-property",
113: new BaseConfigSetPropertyRule());
114:
115: digester.addRule("struts-config/form-beans",
116: new SetActionFormBeanClassRule());
117:
118: digester.addFactoryCreate("struts-config/form-beans/form-bean",
119: new ActionFormBeanFactory(cl));
120: digester.addSetProperties("struts-config/form-beans/form-bean");
121: digester.addSetNext("struts-config/form-beans/form-bean",
122: "addFormBeanConfig",
123: "org.apache.struts.config.FormBeanConfig");
124:
125: digester.addObjectCreate(
126: "struts-config/form-beans/form-bean/form-property",
127: "org.apache.struts.config.FormPropertyConfig",
128: "className");
129: digester
130: .addSetProperties("struts-config/form-beans/form-bean/form-property");
131: digester.addSetNext(
132: "struts-config/form-beans/form-bean/form-property",
133: "addFormPropertyConfig",
134: "org.apache.struts.config.FormPropertyConfig");
135:
136: digester
137: .addRule(
138: "struts-config/form-beans/form-bean/form-property/set-property",
139: new BaseConfigSetPropertyRule());
140:
141: digester.addRule(
142: "struts-config/form-beans/form-bean/set-property",
143: new BaseConfigSetPropertyRule());
144:
145: digester
146: .addObjectCreate(
147: "struts-config/global-exceptions/exception",
148: "org.apache.struts.config.ExceptionConfig",
149: "className");
150: digester
151: .addSetProperties("struts-config/global-exceptions/exception");
152: digester.addSetNext(
153: "struts-config/global-exceptions/exception",
154: "addExceptionConfig",
155: "org.apache.struts.config.ExceptionConfig");
156:
157: digester
158: .addRule(
159: "struts-config/global-exceptions/exception/set-property",
160: new BaseConfigSetPropertyRule());
161:
162: digester.addRule("struts-config/global-forwards",
163: new SetActionForwardClassRule());
164:
165: digester.addFactoryCreate(
166: "struts-config/global-forwards/forward",
167: new GlobalForwardFactory(cl));
168: digester
169: .addSetProperties("struts-config/global-forwards/forward");
170: digester.addSetNext("struts-config/global-forwards/forward",
171: "addForwardConfig",
172: "org.apache.struts.config.ForwardConfig");
173:
174: digester.addRule(
175: "struts-config/global-forwards/forward/set-property",
176: new BaseConfigSetPropertyRule());
177:
178: digester.addObjectCreate("struts-config/message-resources",
179: "org.apache.struts.config.MessageResourcesConfig",
180: "className");
181: digester.addSetProperties("struts-config/message-resources");
182: digester.addSetNext("struts-config/message-resources",
183: "addMessageResourcesConfig",
184: "org.apache.struts.config.MessageResourcesConfig");
185:
186: digester.addRule(
187: "struts-config/message-resources/set-property",
188: new BaseConfigSetPropertyRule());
189:
190: digester.addObjectCreate("struts-config/plug-in",
191: "org.apache.struts.config.PlugInConfig");
192: digester.addSetProperties("struts-config/plug-in");
193: digester.addSetNext("struts-config/plug-in", "addPlugInConfig",
194: "org.apache.struts.config.PlugInConfig");
195:
196: digester.addRule("struts-config/plug-in/set-property",
197: new PlugInSetPropertyRule());
198:
199: // PluginConfig does not extend BaseConfig, at least for now.
200: }
201: }
202:
203: /**
204: * <p> Class that records the name and value of a configuration property to be
205: * used in configuring a <code>PlugIn</code> instance when instantiated. </p>
206: */
207: final class PlugInSetPropertyRule extends Rule {
208: public PlugInSetPropertyRule() {
209: super ();
210: }
211:
212: public void begin(String namespace, String names,
213: Attributes attributes) throws Exception {
214: PlugInConfig plugInConfig = (PlugInConfig) digester.peek();
215:
216: plugInConfig.addProperty(attributes.getValue("property"),
217: attributes.getValue("value"));
218: }
219: }
220:
221: /**
222: * <p> Class that sets the name of the class to use when creating action form
223: * bean instances. The value is set on the object on the top of the stack,
224: * which must be a <code>org.apache.struts.config.ModuleConfig</code>. </p>
225: */
226: final class SetActionFormBeanClassRule extends Rule {
227: public SetActionFormBeanClassRule() {
228: super ();
229: }
230:
231: public void begin(String namespace, String name,
232: Attributes attributes) throws Exception {
233: String className = attributes.getValue("type");
234:
235: if (className != null) {
236: ModuleConfig mc = (ModuleConfig) digester.peek();
237:
238: mc.setActionFormBeanClass(className);
239: }
240: }
241: }
242:
243: /**
244: * <p> A variant of the standard Digester <code>SetPropertyRule</code>. If
245: * the element being processed has a "key" attribute, then the value will be
246: * used to call <code>setProperty(key,value)</code> on the object on top of
247: * the stack, which will be assumed to be of type <code>ActionConfig</code>.
248: * Otherwise, the standard <code>SetPropertyRule</code> behavior is invoked,
249: * and the value will be used to set a bean property on the object on top of
250: * the Digester stack. In that case, the element being processed is assumed to
251: * have attributes "property" and "value". </p>
252: */
253: final class BaseConfigSetPropertyRule extends SetPropertyRule {
254: public BaseConfigSetPropertyRule() {
255: super ("property", "value");
256: }
257:
258: public void begin(Attributes attributes) throws Exception {
259: if (attributes.getIndex("key") == -1) {
260: super .begin(attributes);
261:
262: return;
263: }
264:
265: if (attributes.getIndex("property") != -1) {
266: throw new IllegalArgumentException(
267: "<set-property> accepts only one of 'key' or 'property' attributes.");
268: }
269:
270: Object topOfStack = digester.peek();
271:
272: if (topOfStack instanceof BaseConfig) {
273: BaseConfig config = (BaseConfig) topOfStack;
274:
275: config.setProperty(attributes.getValue("key"), attributes
276: .getValue("value"));
277: } else {
278: throw new IllegalArgumentException(
279: "'key' attribute of <set-property> only applicable to subclasses of BaseConfig; "
280: + "object on top of stack is "
281: + topOfStack
282: + " [key: "
283: + attributes.getValue("key")
284: + ", value: "
285: + attributes.getValue("value") + "]");
286: }
287: }
288: }
289:
290: /**
291: * <p> An object creation factory which creates action form bean instances,
292: * taking into account the default class name, which may have been specified
293: * on the parent element and which is made available through the object on the
294: * top of the stack, which must be a <code>org.apache.struts.config.ModuleConfig</code>.
295: * </p>
296: */
297: final class ActionFormBeanFactory extends AbstractObjectCreationFactory {
298: private ClassLoader cl;
299:
300: public ActionFormBeanFactory(ClassLoader cl) {
301: super ();
302: this .cl = cl;
303: }
304:
305: public Object createObject(Attributes attributes) {
306: // Identify the name of the class to instantiate
307: String className = attributes.getValue("className");
308:
309: if (className == null) {
310: ModuleConfig mc = (ModuleConfig) digester.peek();
311:
312: className = mc.getActionFormBeanClass();
313: }
314:
315: // Instantiate the new object and return it
316: Object actionFormBean = null;
317:
318: try {
319: actionFormBean = RequestUtils.applicationInstance(
320: className, cl);
321: } catch (Exception e) {
322: digester.getLogger().error(
323: "ActionFormBeanFactory.createObject: ", e);
324: }
325:
326: return actionFormBean;
327: }
328: }
329:
330: /**
331: * <p> Class that sets the name of the class to use when creating action
332: * mapping instances. The value is set on the object on the top of the stack,
333: * which must be a <code>org.apache.struts.config.ModuleConfig</code>. </p>
334: */
335: final class SetActionMappingClassRule extends Rule {
336: public SetActionMappingClassRule() {
337: super ();
338: }
339:
340: public void begin(String namespace, String name,
341: Attributes attributes) throws Exception {
342: String className = attributes.getValue("type");
343:
344: if (className != null) {
345: ModuleConfig mc = (ModuleConfig) digester.peek();
346:
347: mc.setActionMappingClass(className);
348: }
349: }
350: }
351:
352: /**
353: * <p> An object creation factory which creates action mapping instances,
354: * taking into account the default class name, which may have been specified
355: * on the parent element and which is made available through the object on the
356: * top of the stack, which must be a <code>org.apache.struts.config.ModuleConfig</code>.
357: * </p>
358: */
359: final class ActionMappingFactory extends AbstractObjectCreationFactory {
360: private ClassLoader cl;
361:
362: public ActionMappingFactory(ClassLoader cl) {
363: super ();
364: this .cl = cl;
365: }
366:
367: public Object createObject(Attributes attributes) {
368: // Identify the name of the class to instantiate
369: String className = attributes.getValue("className");
370:
371: if (className == null) {
372: ModuleConfig mc = (ModuleConfig) digester.peek();
373:
374: className = mc.getActionMappingClass();
375: }
376:
377: // Instantiate the new object and return it
378: Object actionMapping = null;
379:
380: try {
381: actionMapping = RequestUtils.applicationInstance(className,
382: cl);
383: } catch (Exception e) {
384: digester.getLogger().error(
385: "ActionMappingFactory.createObject: ", e);
386: }
387:
388: return actionMapping;
389: }
390: }
391:
392: /**
393: * <p> Class that sets the name of the class to use when creating global
394: * forward instances. The value is set on the object on the top of the stack,
395: * which must be a <code>org.apache.struts.config.ModuleConfig</code>. </p>
396: */
397: final class SetActionForwardClassRule extends Rule {
398: public SetActionForwardClassRule() {
399: super ();
400: }
401:
402: public void begin(String namespace, String name,
403: Attributes attributes) throws Exception {
404: String className = attributes.getValue("type");
405:
406: if (className != null) {
407: ModuleConfig mc = (ModuleConfig) digester.peek();
408:
409: mc.setActionForwardClass(className);
410: }
411: }
412: }
413:
414: /**
415: * <p> An object creation factory which creates global forward instances,
416: * taking into account the default class name, which may have been specified
417: * on the parent element and which is made available through the object on the
418: * top of the stack, which must be a <code>org.apache.struts.config.ModuleConfig</code>.
419: * </p>
420: */
421: final class GlobalForwardFactory extends AbstractObjectCreationFactory {
422: private ClassLoader cl;
423:
424: public GlobalForwardFactory(ClassLoader cl) {
425: super ();
426: this .cl = cl;
427: }
428:
429: public Object createObject(Attributes attributes) {
430: // Identify the name of the class to instantiate
431: String className = attributes.getValue("className");
432:
433: if (className == null) {
434: ModuleConfig mc = (ModuleConfig) digester.peek();
435:
436: className = mc.getActionForwardClass();
437: }
438:
439: // Instantiate the new object and return it
440: Object globalForward = null;
441:
442: try {
443: globalForward = RequestUtils.applicationInstance(className,
444: cl);
445: } catch (Exception e) {
446: digester.getLogger().error(
447: "GlobalForwardFactory.createObject: ", e);
448: }
449:
450: return globalForward;
451: }
452: }
453:
454: /**
455: * <p> An object creation factory which creates action forward instances,
456: * taking into account the default class name, which may have been specified
457: * on the parent element and which is made available through the object on the
458: * top of the stack, which must be a <code>org.apache.struts.config.ModuleConfig</code>.
459: * </p>
460: */
461: final class ActionForwardFactory extends AbstractObjectCreationFactory {
462: private ClassLoader cl;
463:
464: public ActionForwardFactory(ClassLoader cl) {
465: super ();
466: this .cl = cl;
467: }
468:
469: public Object createObject(Attributes attributes) {
470: // Identify the name of the class to instantiate
471: String className = attributes.getValue("className");
472:
473: if (className == null) {
474: ModuleConfig mc = (ModuleConfig) digester.peek(1);
475:
476: className = mc.getActionForwardClass();
477: }
478:
479: // Instantiate the new object and return it
480: Object actionForward = null;
481:
482: try {
483: actionForward = RequestUtils.applicationInstance(className,
484: cl);
485: } catch (Exception e) {
486: digester.getLogger().error(
487: "ActionForwardFactory.createObject: ", e);
488: }
489:
490: return actionForward;
491: }
492: }
|