001: /* $Id: FactoryCreateRule.java 467222 2006-10-24 03:17:11Z markt $
002: *
003: * Licensed to the Apache Software Foundation (ASF) under one or more
004: * contributor license agreements. See the NOTICE file distributed with
005: * this work for additional information regarding copyright ownership.
006: * The ASF licenses this file to You under the Apache License, Version 2.0
007: * (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: package org.apache.tomcat.util.digester;
020:
021: import org.xml.sax.Attributes;
022:
023: /**
024: * <p>Rule implementation that uses an {@link ObjectCreationFactory} to create
025: * a new object which it pushes onto the object stack. When the element is
026: * complete, the object will be popped.</p>
027: *
028: * <p>This rule is intended in situations where the element's attributes are
029: * needed before the object can be created. A common senario is for the
030: * ObjectCreationFactory implementation to use the attributes as parameters
031: * in a call to either a factory method or to a non-empty constructor.
032: */
033:
034: public class FactoryCreateRule extends Rule {
035:
036: // ----------------------------------------------------------- Fields
037:
038: /** Should exceptions thrown by the factory be ignored? */
039: private boolean ignoreCreateExceptions;
040: /** Stock to manage */
041: private ArrayStack exceptionIgnoredStack;
042:
043: // ----------------------------------------------------------- Constructors
044:
045: /**
046: * Construct a factory create rule that will use the specified
047: * class name to create an {@link ObjectCreationFactory} which will
048: * then be used to create an object and push it on the stack.
049: *
050: * @param digester The associated Digester
051: * @param className Java class name of the object creation factory class
052: *
053: * @deprecated The digester instance is now set in the {@link Digester#addRule} method.
054: * Use {@link #FactoryCreateRule(String className)} instead.
055: */
056: public FactoryCreateRule(Digester digester, String className) {
057:
058: this (className);
059:
060: }
061:
062: /**
063: * Construct a factory create rule that will use the specified
064: * class to create an {@link ObjectCreationFactory} which will
065: * then be used to create an object and push it on the stack.
066: *
067: * @param digester The associated Digester
068: * @param clazz Java class name of the object creation factory class
069: *
070: * @deprecated The digester instance is now set in the {@link Digester#addRule} method.
071: * Use {@link #FactoryCreateRule(Class clazz)} instead.
072: */
073: public FactoryCreateRule(Digester digester, Class clazz) {
074:
075: this (clazz);
076:
077: }
078:
079: /**
080: * Construct a factory create rule that will use the specified
081: * class name (possibly overridden by the specified attribute if present)
082: * to create an {@link ObjectCreationFactory}, which will then be used
083: * to instantiate an object instance and push it onto the stack.
084: *
085: * @param digester The associated Digester
086: * @param className Default Java class name of the factory class
087: * @param attributeName Attribute name which, if present, contains an
088: * override of the class name of the object creation factory to create.
089: *
090: * @deprecated The digester instance is now set in the {@link Digester#addRule} method.
091: * Use {@link #FactoryCreateRule(String className, String attributeName)} instead.
092: */
093: public FactoryCreateRule(Digester digester, String className,
094: String attributeName) {
095:
096: this (className, attributeName);
097:
098: }
099:
100: /**
101: * Construct a factory create rule that will use the specified
102: * class (possibly overridden by the specified attribute if present)
103: * to create an {@link ObjectCreationFactory}, which will then be used
104: * to instantiate an object instance and push it onto the stack.
105: *
106: * @param digester The associated Digester
107: * @param clazz Default Java class name of the factory class
108: * @param attributeName Attribute name which, if present, contains an
109: * override of the class name of the object creation factory to create.
110: *
111: * @deprecated The digester instance is now set in the {@link Digester#addRule} method.
112: * Use {@link #FactoryCreateRule(Class clazz, String attributeName)} instead.
113: */
114: public FactoryCreateRule(Digester digester, Class clazz,
115: String attributeName) {
116:
117: this (clazz, attributeName);
118:
119: }
120:
121: /**
122: * Construct a factory create rule using the given, already instantiated,
123: * {@link ObjectCreationFactory}.
124: *
125: * @param digester The associated Digester
126: * @param creationFactory called on to create the object.
127: *
128: * @deprecated The digester instance is now set in the {@link Digester#addRule} method.
129: * Use {@link #FactoryCreateRule(ObjectCreationFactory creationFactory)} instead.
130: */
131: public FactoryCreateRule(Digester digester,
132: ObjectCreationFactory creationFactory) {
133:
134: this (creationFactory);
135:
136: }
137:
138: /**
139: * <p>Construct a factory create rule that will use the specified
140: * class name to create an {@link ObjectCreationFactory} which will
141: * then be used to create an object and push it on the stack.</p>
142: *
143: * <p>Exceptions thrown during the object creation process will be propagated.</p>
144: *
145: * @param className Java class name of the object creation factory class
146: */
147: public FactoryCreateRule(String className) {
148:
149: this (className, false);
150:
151: }
152:
153: /**
154: * <p>Construct a factory create rule that will use the specified
155: * class to create an {@link ObjectCreationFactory} which will
156: * then be used to create an object and push it on the stack.</p>
157: *
158: * <p>Exceptions thrown during the object creation process will be propagated.</p>
159: *
160: * @param clazz Java class name of the object creation factory class
161: */
162: public FactoryCreateRule(Class clazz) {
163:
164: this (clazz, false);
165:
166: }
167:
168: /**
169: * <p>Construct a factory create rule that will use the specified
170: * class name (possibly overridden by the specified attribute if present)
171: * to create an {@link ObjectCreationFactory}, which will then be used
172: * to instantiate an object instance and push it onto the stack.</p>
173: *
174: * <p>Exceptions thrown during the object creation process will be propagated.</p>
175: *
176: * @param className Default Java class name of the factory class
177: * @param attributeName Attribute name which, if present, contains an
178: * override of the class name of the object creation factory to create.
179: */
180: public FactoryCreateRule(String className, String attributeName) {
181:
182: this (className, attributeName, false);
183:
184: }
185:
186: /**
187: * <p>Construct a factory create rule that will use the specified
188: * class (possibly overridden by the specified attribute if present)
189: * to create an {@link ObjectCreationFactory}, which will then be used
190: * to instantiate an object instance and push it onto the stack.</p>
191: *
192: * <p>Exceptions thrown during the object creation process will be propagated.</p>
193: *
194: * @param clazz Default Java class name of the factory class
195: * @param attributeName Attribute name which, if present, contains an
196: * override of the class name of the object creation factory to create.
197: */
198: public FactoryCreateRule(Class clazz, String attributeName) {
199:
200: this (clazz, attributeName, false);
201:
202: }
203:
204: /**
205: * <p>Construct a factory create rule using the given, already instantiated,
206: * {@link ObjectCreationFactory}.</p>
207: *
208: * <p>Exceptions thrown during the object creation process will be propagated.</p>
209: *
210: * @param creationFactory called on to create the object.
211: */
212: public FactoryCreateRule(ObjectCreationFactory creationFactory) {
213:
214: this (creationFactory, false);
215:
216: }
217:
218: /**
219: * Construct a factory create rule that will use the specified
220: * class name to create an {@link ObjectCreationFactory} which will
221: * then be used to create an object and push it on the stack.
222: *
223: * @param className Java class name of the object creation factory class
224: * @param ignoreCreateExceptions if true, exceptions thrown by the object
225: * creation factory
226: * will be ignored.
227: */
228: public FactoryCreateRule(String className,
229: boolean ignoreCreateExceptions) {
230:
231: this (className, null, ignoreCreateExceptions);
232:
233: }
234:
235: /**
236: * Construct a factory create rule that will use the specified
237: * class to create an {@link ObjectCreationFactory} which will
238: * then be used to create an object and push it on the stack.
239: *
240: * @param clazz Java class name of the object creation factory class
241: * @param ignoreCreateExceptions if true, exceptions thrown by the
242: * object creation factory
243: * will be ignored.
244: */
245: public FactoryCreateRule(Class clazz, boolean ignoreCreateExceptions) {
246:
247: this (clazz, null, ignoreCreateExceptions);
248:
249: }
250:
251: /**
252: * Construct a factory create rule that will use the specified
253: * class name (possibly overridden by the specified attribute if present)
254: * to create an {@link ObjectCreationFactory}, which will then be used
255: * to instantiate an object instance and push it onto the stack.
256: *
257: * @param className Default Java class name of the factory class
258: * @param attributeName Attribute name which, if present, contains an
259: * override of the class name of the object creation factory to create.
260: * @param ignoreCreateExceptions if true, exceptions thrown by the object
261: * creation factory will be ignored.
262: */
263: public FactoryCreateRule(String className, String attributeName,
264: boolean ignoreCreateExceptions) {
265:
266: this .className = className;
267: this .attributeName = attributeName;
268: this .ignoreCreateExceptions = ignoreCreateExceptions;
269:
270: }
271:
272: /**
273: * Construct a factory create rule that will use the specified
274: * class (possibly overridden by the specified attribute if present)
275: * to create an {@link ObjectCreationFactory}, which will then be used
276: * to instantiate an object instance and push it onto the stack.
277: *
278: * @param clazz Default Java class name of the factory class
279: * @param attributeName Attribute name which, if present, contains an
280: * override of the class name of the object creation factory to create.
281: * @param ignoreCreateExceptions if true, exceptions thrown by the object
282: * creation factory will be ignored.
283: */
284: public FactoryCreateRule(Class clazz, String attributeName,
285: boolean ignoreCreateExceptions) {
286:
287: this (clazz.getName(), attributeName, ignoreCreateExceptions);
288:
289: }
290:
291: /**
292: * Construct a factory create rule using the given, already instantiated,
293: * {@link ObjectCreationFactory}.
294: *
295: * @param creationFactory called on to create the object.
296: * @param ignoreCreateExceptions if true, exceptions thrown by the object
297: * creation factory will be ignored.
298: */
299: public FactoryCreateRule(ObjectCreationFactory creationFactory,
300: boolean ignoreCreateExceptions) {
301:
302: this .creationFactory = creationFactory;
303: this .ignoreCreateExceptions = ignoreCreateExceptions;
304: }
305:
306: // ----------------------------------------------------- Instance Variables
307:
308: /**
309: * The attribute containing an override class name if it is present.
310: */
311: protected String attributeName = null;
312:
313: /**
314: * The Java class name of the ObjectCreationFactory to be created.
315: * This class must have a no-arguments constructor.
316: */
317: protected String className = null;
318:
319: /**
320: * The object creation factory we will use to instantiate objects
321: * as required based on the attributes specified in the matched XML
322: * element.
323: */
324: protected ObjectCreationFactory creationFactory = null;
325:
326: // --------------------------------------------------------- Public Methods
327:
328: /**
329: * Process the beginning of this element.
330: *
331: * @param attributes The attribute list of this element
332: */
333: public void begin(String namespace, String name,
334: Attributes attributes) throws Exception {
335:
336: if (ignoreCreateExceptions) {
337:
338: if (exceptionIgnoredStack == null) {
339: exceptionIgnoredStack = new ArrayStack();
340: }
341:
342: try {
343: Object instance = getFactory(attributes).createObject(
344: attributes);
345:
346: if (digester.log.isDebugEnabled()) {
347: digester.log.debug("[FactoryCreateRule]{"
348: + digester.match + "} New "
349: + instance.getClass().getName());
350: }
351: digester.push(instance);
352: exceptionIgnoredStack.push(Boolean.FALSE);
353:
354: } catch (Exception e) {
355: // log message and error
356: if (digester.log.isInfoEnabled()) {
357: digester.log
358: .info("[FactoryCreateRule] Create exception ignored: "
359: + ((e.getMessage() == null) ? e
360: .getClass().getName() : e
361: .getMessage()));
362: if (digester.log.isDebugEnabled()) {
363: digester.log
364: .debug(
365: "[FactoryCreateRule] Ignored exception:",
366: e);
367: }
368: }
369: exceptionIgnoredStack.push(Boolean.TRUE);
370: }
371:
372: } else {
373: Object instance = getFactory(attributes).createObject(
374: attributes);
375:
376: if (digester.log.isDebugEnabled()) {
377: digester.log.debug("[FactoryCreateRule]{"
378: + digester.match + "} New "
379: + instance.getClass().getName());
380: }
381: digester.push(instance);
382: }
383: }
384:
385: /**
386: * Process the end of this element.
387: */
388: public void end(String namespace, String name) throws Exception {
389:
390: // check if object was created
391: // this only happens if an exception was thrown and we're ignoring them
392: if (ignoreCreateExceptions && exceptionIgnoredStack != null
393: && !(exceptionIgnoredStack.empty())) {
394:
395: if (((Boolean) exceptionIgnoredStack.pop()).booleanValue()) {
396: // creation exception was ignored
397: // nothing was put onto the stack
398: if (digester.log.isTraceEnabled()) {
399: digester.log
400: .trace("[FactoryCreateRule] No creation so no push so no pop");
401: }
402: return;
403: }
404: }
405:
406: Object top = digester.pop();
407: if (digester.log.isDebugEnabled()) {
408: digester.log.debug("[FactoryCreateRule]{" + digester.match
409: + "} Pop " + top.getClass().getName());
410: }
411:
412: }
413:
414: /**
415: * Clean up after parsing is complete.
416: */
417: public void finish() throws Exception {
418:
419: if (attributeName != null) {
420: creationFactory = null;
421: }
422:
423: }
424:
425: /**
426: * Render a printable version of this Rule.
427: */
428: public String toString() {
429:
430: StringBuffer sb = new StringBuffer("FactoryCreateRule[");
431: sb.append("className=");
432: sb.append(className);
433: sb.append(", attributeName=");
434: sb.append(attributeName);
435: if (creationFactory != null) {
436: sb.append(", creationFactory=");
437: sb.append(creationFactory);
438: }
439: sb.append("]");
440: return (sb.toString());
441:
442: }
443:
444: // ------------------------------------------------------ Protected Methods
445:
446: /**
447: * Return an instance of our associated object creation factory,
448: * creating one if necessary.
449: *
450: * @param attributes Attributes passed to our factory creation element
451: *
452: * @exception Exception if any error occurs
453: */
454: protected ObjectCreationFactory getFactory(Attributes attributes)
455: throws Exception {
456:
457: if (creationFactory == null) {
458: String realClassName = className;
459: if (attributeName != null) {
460: String value = attributes.getValue(attributeName);
461: if (value != null) {
462: realClassName = value;
463: }
464: }
465: if (digester.log.isDebugEnabled()) {
466: digester.log.debug("[FactoryCreateRule]{"
467: + digester.match + "} New factory "
468: + realClassName);
469: }
470: Class clazz = digester.getClassLoader().loadClass(
471: realClassName);
472: creationFactory = (ObjectCreationFactory) clazz
473: .newInstance();
474: creationFactory.setDigester(digester);
475: }
476: return (creationFactory);
477:
478: }
479: }
|