001: /*
002: * Koala Bean Markup Language - Copyright (C) 1999 Dyade
003: *
004: * Permission is hereby granted, free of charge, to any person obtaining a
005: * copy of this software and associated documentation files
006: * (the "Software"), to deal in the Software without restriction, including
007: * without limitation the rights to use, copy, modify, merge, publish,
008: * distribute, sublicense, and/or sell copies of the Software, and to permit
009: * persons to whom the Software is furnished to do so, subject to the
010: * following conditions:
011: * The above copyright notice and this permission notice shall be included
012: * in all copies or substantial portions of the Software.
013: *
014: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
015: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
016: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
017: * IN NO EVENT SHALL Dyade BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
018: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
019: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
020: * DEALINGS IN THE SOFTWARE.
021: *
022: * Except as contained in this notice, the name of Dyade shall not be
023: * used in advertising or otherwise to promote the sale, use or other
024: * dealings in this Software without prior written authorization from
025: * Dyade.
026: *
027: * $Id: KBMLDeserializer.java,v 1.13 2000/08/01 13:34:23 tkormann Exp $
028: * Author: Thierry.Kormann@sophia.inria.fr
029: */
030:
031: package fr.dyade.koala.xml.kbml;
032:
033: import java.io.*;
034: import java.util.Hashtable;
035: import java.util.Vector;
036: import java.util.Stack;
037: import java.beans.*;
038: import java.lang.reflect.*;
039: import org.xml.sax.*;
040:
041: /**
042: * The class enables to create JavaBeans from an XML document. Example of use:
043: *
044: * <pre><code>
045: * FileInputStream istream = new FileInputStream("test.kbml");
046: * KBMLDeserializer bxi = new KBMLDeserializer(istream);
047: * bean1 = bxi.readBean();
048: * bean2 = bxi.readBean();
049: * bxi.close();
050: * </code></pre>
051: *
052: * @author Thierry.Kormann@sophia.inria.fr
053: */
054: public class KBMLDeserializer {
055:
056: /** The KBML version. */
057: public static final String VERSION = KBMLSerializer.VERSION;
058: /** The Hashtable where keys are Object and values are ID. */
059: protected Hashtable beansCache = new Hashtable();
060: /** The underlying input stream where to get the beans. */
061: protected InputStream istream;
062: /** The underlying reader where to get the beans. */
063: protected Reader reader;
064: /** The children of the kbml tag. */
065: private Object[] beans;
066: /** The current child index. */
067: private int currentBeanIndex = 0;
068: /** A SAX parser. */
069: private Parser parser;
070: /** The error handler used to notify no-fatal errors. */
071: protected ErrorHandler handler;
072:
073: /**
074: * Constructs a new deserializer with the specified input
075: * stream. The InputStream must contains the XML document.
076: *
077: * @param istream the input stream
078: *
079: * @exception ClassNotFoundException if the SAX parser can't be
080: * found (check your CLASSPATH)
081: *
082: * @exception InstantiationException if the SAX parser can't be
083: * instanciated (it's an interface or abstract class)
084: *
085: * @exception IllegalAccessException The SAX parser class was
086: * found, but you do not have permission to load it.
087: *
088: * @exception java.lang.ClassCastException The SAX parser class
089: * was found and instantiated, but does not implement
090: * org.xml.sax.Parser.
091: */
092: public KBMLDeserializer(InputStream istream)
093: throws ClassNotFoundException, InstantiationException,
094: IllegalAccessException, ClassCastException {
095: this (istream, new KBMLDeserializerDefaultErrorHandler());
096: }
097:
098: /**
099: * Constructs a new deserializer with the specified input stream
100: * and error handler.
101: *
102: * @param istream the input stream
103: * @param handler the handler to track the no-fatal error
104: *
105: * @exception ClassNotFoundException if the SAX parser can't be
106: * found (check your CLASSPATH)
107: *
108: * @exception InstantiationException if the SAX parser can't be
109: * instanciated (it's an interface or abstract class)
110: *
111: * @exception IllegalAccessException The SAX parser class was
112: * found, but you do not have permission to load it.
113: *
114: * @exception java.lang.ClassCastException The SAX parser class
115: * was found and instantiated, but does not implement
116: * org.xml.sax.Parser.
117: */
118: public KBMLDeserializer(InputStream istream, ErrorHandler handler)
119: throws ClassNotFoundException, InstantiationException,
120: IllegalAccessException, ClassCastException {
121: this .istream = istream;
122: this .handler = handler;
123: parser = fr.dyade.koala.xml.sax.ParserFactory.makeParser();
124: parser.setDocumentHandler(new SAXHandler());
125: parser.setErrorHandler(new SAXErrorHandler());
126: initializePropertyEditorManager();
127: }
128:
129: /**
130: * Constructs a new deserializer with the specified reader. The
131: * Reader must contains the XML document.
132: *
133: * @param reader the reader
134: *
135: * @exception ClassNotFoundException if the SAX parser can't be
136: * found (check your CLASSPATH)
137: *
138: * @exception InstantiationException if the SAX parser can't be
139: * instanciated (it's an interface or abstract class)
140: *
141: * @exception IllegalAccessException The SAX parser class was
142: * found, but you do not have permission to load it.
143: *
144: * @exception java.lang.ClassCastException The SAX parser class
145: * was found and instantiated, but does not implement
146: * org.xml.sax.Parser.
147: */
148: public KBMLDeserializer(Reader reader)
149: throws ClassNotFoundException, InstantiationException,
150: IllegalAccessException, ClassCastException {
151: this (reader, new KBMLDeserializerDefaultErrorHandler());
152: }
153:
154: /**
155: * Constructs a new deserializer with the specified reader
156: * and error handler.
157: *
158: * @param reader the reader
159: * @param handler the handler to track the no-fatal error
160: *t
161: * @exception ClassNotFoundException if the SAX parser can't be
162: * found (check your CLASSPATH)
163: *
164: * @exception InstantiationException if the SAX parser can't be
165: * instanciated (it's an interface or abstract class)
166: *
167: * @exception IllegalAccessException The SAX parser class was
168: * found, but you do not have permission to load it.
169: *
170: * @exception java.lang.ClassCastException The SAX parser class
171: * was found and instantiated, but does not implement
172: * org.xml.sax.Parser.
173: */
174: public KBMLDeserializer(Reader reader, ErrorHandler handler)
175: throws ClassNotFoundException, InstantiationException,
176: IllegalAccessException, ClassCastException {
177: this .reader = reader;
178: this .handler = handler;
179: parser = fr.dyade.koala.xml.sax.ParserFactory.makeParser();
180: parser.setDocumentHandler(new SAXHandler());
181: parser.setErrorHandler(new SAXErrorHandler());
182: initializePropertyEditorManager();
183: }
184:
185: /**
186: * Reads next bean object from the XML input stream or reader.
187: * @exception IOException if an I/O error occurs
188: * @exception SAXException if an error occrus while parsing the xml document
189: */
190: public Object readBean() throws IOException, SAXException {
191: if (beans == null) {
192: if (istream != null) {
193: parser.parse(new InputSource(istream));
194: } else {
195: parser.parse(new InputSource(reader));
196: }
197: }
198: if (currentBeanIndex < beans.length) {
199: return beans[currentBeanIndex++];
200: } else {
201: return null;
202: }
203: }
204:
205: /**
206: * Closes the input stream.
207: * @exception IOException if an I/O error occurs.
208: */
209: public void close() throws IOException {
210: if (istream != null) {
211: istream.close();
212: } else {
213: reader.close();
214: }
215: }
216:
217: /**
218: * Returns the internal cache used by the deserializer. Use the ID of
219: * an element as a key to get its associated bean.
220: */
221: public Hashtable getBeansCache() {
222: return beansCache;
223: }
224:
225: /**
226: * Registers useful PropertyEditors to the java.beans.PropertyEditorManager.
227: * @see Util#initializePropertyEditorManager
228: */
229: protected void initializePropertyEditorManager() {
230: Util.initializePropertyEditorManager();
231: }
232:
233: /**
234: * Returns an instance that corresponds to the specified
235: * classname. This method is invoked each time the class attribute
236: * is specified while parsing a bean element from the XML
237: * document. Default behavior use the default class loader to
238: * instanciate the bean.
239: *
240: * <p>Override to have the opportunity to use custom class
241: * loaders. For example, the class name can be an URL that points
242: * to a class file. This method parses the class name and use an
243: * URL class loader to create the right instance.
244: *
245: * @see KBMLSerializer#getBeanClassName(java.lang.Object)
246: *
247: * @exception IOException if the bean can't be instantiate by the
248: * <code>Beans.instanciate(ClassLoader, String)</code> method
249: *
250: * @exception ClassNotFoundException if the bean can't be
251: * found (check your CLASSPATH)
252: *
253: * @exception InstantiationException if the bean can't be
254: * instanciated (it's an interface or abstract class)
255: *
256: * @exception IllegalAccessException The bean class was
257: * found, but you do not have permission to load it.
258: *
259: * @exception NoSuchMethodError The zero-argument constructor of
260: * the bean was not found.
261: *
262: * @return a new bean instance corresponding to the specified class name.
263: * @since KBML 2.2
264: */
265: protected Object instanciateBean(String className)
266: throws ClassNotFoundException, IllegalAccessException,
267: InstantiationException, NoSuchMethodError, IOException {
268: return Beans.instantiate(this .getClass().getClassLoader(),
269: className);
270: }
271:
272: /**
273: * A SAX handler that creates JavaBeans.
274: */
275: private class SAXHandler extends HandlerBase {
276:
277: Stack stack = new Stack();
278: StringBuffer content = new StringBuffer();
279:
280: public void startElement(String name, AttributeList atts) {
281: // dispatch start-tag
282: if (name.equals("property")) {
283: handlePropertyStartElement(atts);
284: } else if (name.equals("value")) {
285: handleValueStartElement(atts);
286: } else if (name.equals("bean")) {
287: handleBeanStartElement(atts);
288: } else if (name.equals("null")) {
289: handleNullStartElement();
290: } else if (name.equals("valueArray")) {
291: handleValueArrayStartElement(atts);
292: } else if (name.equals("kbml")) {
293: String version = getAttributeValue(atts, "version");
294: if (version == null) {
295: throw new IllegalArgumentException(
296: "Bad KBML file, version attribute not found.");
297: }
298: int i = version.indexOf('.');
299: if (i < 0) {
300: throw new IllegalArgumentException(
301: "Bad version format : "
302: + version
303: + "\n"
304: + "Correct version format is : <major>.<minor>");
305: }
306: String vmajor = version.substring(0, i);
307: String Vmajor = VERSION.substring(0, version
308: .indexOf('.'));
309: if (!vmajor.equals(Vmajor)) {
310: throw new IllegalArgumentException(
311: "Bad KBML version, current version is "
312: + VERSION
313: + " and document version is "
314: + version);
315: }
316: }
317: }
318:
319: public void endElement(String name) {
320: // dispatch end-tag
321: if (name.equals("property")) {
322: handlePropertyEndElement();
323: } else if (name.equals("value")) {
324: handleValueEndElement();
325: } else if (name.equals("valueArray")) {
326: handleValueArrayEndElement();
327: }
328: }
329:
330: public void endDocument() {
331: beans = new Object[stack.size()];
332: stack.copyInto(beans);
333: stack.removeAllElements();
334: content = null;
335: }
336:
337: public void characters(char ch[], int start, int length)
338: throws SAXException {
339: content.append(ch, start, length);
340: }
341:
342: // handle the bean start-tag
343: void handleBeanStartElement(AttributeList atts) {
344: String src = getAttributeValue(atts, "source");
345: Object bean;
346: if (src != null) {
347: bean = beansCache.get(src);
348: stack.push(bean);
349: } else {
350: String className = getAttributeValue(atts, "class");
351: try {
352: bean = instanciateBean(className);
353: stack.push(bean);
354: String id = getAttributeValue(atts, "id");
355: if (id != null) {
356: beansCache.put(id, bean);
357: }
358: } catch (IOException ex) {
359: handler.instanciateBean(className, ex);
360: stack.push(ERROR);
361: } catch (ClassNotFoundException ex) {
362: handler.instanciateBean(className, ex);
363: stack.push(ERROR);
364: } catch (IllegalAccessException ex) {
365: handler.instanciateBean(className, ex);
366: stack.push(ERROR);
367: } catch (InstantiationException ex) {
368: handler.instanciateBean(className, ex);
369: stack.push(ERROR);
370: } catch (NoSuchMethodError err) {
371: handler.instanciateBean(className, err);
372: stack.push(ERROR);
373: }
374: }
375: }
376:
377: // handle property start-tag
378: void handlePropertyStartElement(AttributeList atts) {
379: Object bean = stack.peek();
380: try {
381: BeanInfo info = Introspector.getBeanInfo(bean
382: .getClass());
383: String name = getAttributeValue(atts, "name");
384: PropertyDescriptor[] pds = info
385: .getPropertyDescriptors();
386: PropertyDescriptor pd = Util.getPropertyDescriptor(pds,
387: name);
388: if (pd == null) {
389: handler.propertyDescriptor(bean, name);
390: stack.push(ERROR);
391: } else {
392: stack.push(pd);
393: }
394: } catch (IntrospectionException ex) {
395: handler.introspector(bean, ex);
396: stack.push(ERROR);
397: }
398: }
399:
400: // handle the property end-tag
401: void handlePropertyEndElement() {
402: Object v1 = stack.pop();
403: Object v2 = stack.pop();
404: Object bean = stack.peek();
405: if (v1 != ERROR && v2 != ERROR) {
406: Object value = v1;
407: PropertyDescriptor pd = (PropertyDescriptor) v2;
408: Method writeMethod = pd.getWriteMethod();
409: if (writeMethod != null) {
410: // use the write method
411: Object[] args = new Object[] { value };
412: try {
413: writeMethod.invoke(bean, args);
414: } catch (IllegalAccessException ex) {
415: handler.writeMethod(bean, pd, ex);
416: } catch (InvocationTargetException ex) {
417: handler.writeMethod(bean, pd, ex);
418: } catch (IllegalArgumentException ex) {
419: handler.writeMethod(bean, pd, ex);
420: }
421: } else if (pd instanceof IndexedPropertyDescriptor) {
422: // use the indexed write method
423: IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd;
424: Method iwriteMethod = ipd.getIndexedWriteMethod();
425: if (iwriteMethod != null) {
426: // set values using the indexed write method
427: Object[] valueArray = (Object[]) value;
428: Object[] args = new Object[2];
429: try {
430: for (int i = 0; i < valueArray.length; ++i) {
431: args[0] = new Integer(i);
432: args[1] = valueArray[i];
433: iwriteMethod.invoke(bean, args);
434: }
435: } catch (IllegalAccessException ex) {
436: handler.writeMethod(bean, pd, ex);
437: } catch (InvocationTargetException ex) {
438: handler.writeMethod(bean, pd, ex);
439: } catch (IllegalArgumentException ex) {
440: handler.writeMethod(bean, pd, ex);
441: }
442: } else {
443: // indexed write method not found
444: handler.writeMethod(bean, pd);
445: }
446: } else {
447: // write method and indexed write method not found
448: handler.writeMethod(bean, pd);
449: }
450: }
451: }
452:
453: // handle the valueArray start-tag
454: void handleValueArrayStartElement(AttributeList atts) {
455: String src = getAttributeValue(atts, "source");
456: if (src != null) {
457: stack.push(new SourceRef(src));
458: } else {
459: String id = getAttributeValue(atts, "id");
460: stack.push(new ValueArrayDecl(id));
461: }
462: }
463:
464: // handle the valueArray end-tag
465: void handleValueArrayEndElement() {
466: if (stack.peek() instanceof SourceRef) {
467: SourceRef ref = (SourceRef) stack.pop();
468: stack.push(beansCache.get(ref.source));
469: } else {
470: Vector subValues = new Vector();
471: while (!(stack.peek() instanceof ValueArrayDecl)) {
472: subValues.addElement(stack.pop());
473: }
474: ValueArrayDecl decl = (ValueArrayDecl) stack.pop();
475: PropertyDescriptor pd = currentPropertyDescriptor();
476: Class valueClass = pd.getPropertyType()
477: .getComponentType();
478: Object array = Array.newInstance(valueClass, subValues
479: .size());
480: int length = subValues.size();
481: for (int i = 0; i < length; ++i) {
482: Array.set(array, length - i - 1, subValues
483: .elementAt(i));
484: }
485: stack.push(array);
486: if (decl.id != null) {
487: beansCache.put(decl.id, array);
488: }
489: }
490: }
491:
492: // handle the value start-tag, push a value if reference or class
493: void handleValueStartElement(AttributeList atts) {
494: // reset content
495: content.setLength(0);
496: // push a value declaration object or source ref
497: String src = getAttributeValue(atts, "source");
498: if (src != null) {
499: stack.push(new SourceRef(src));
500: } else {
501: String id = getAttributeValue(atts, "id");
502: String className = getAttributeValue(atts, "class");
503: Class valueClass;
504: if (className == null) {
505: PropertyDescriptor pd = currentPropertyDescriptor();
506: if (pd.getPropertyType().isArray()) {
507: valueClass = pd.getPropertyType()
508: .getComponentType();
509: } else {
510: valueClass = pd.getPropertyType();
511: }
512: } else {
513: try {
514: valueClass = Class.forName(className);
515: } catch (ClassNotFoundException ex) {
516: handler.instanciateValue(className, ex);
517: stack.push(ERROR);
518: return;
519: }
520: }
521: stack.push(new ValueDecl(id, valueClass));
522: }
523: }
524:
525: // handle the value end-tag, push a value if content not empty
526: void handleValueEndElement() {
527: if (stack.peek() instanceof SourceRef) {
528: SourceRef ref = (SourceRef) stack.pop();
529: stack.push(beansCache.get(ref.source));
530: } else {
531: ValueDecl decl = (ValueDecl) stack.pop();
532: PropertyDescriptor pd = currentPropertyDescriptor();
533: Object value = getContentValue(pd, decl.valueClass);
534: stack.push(value);
535: if (decl.id != null) {
536: beansCache.put(decl.id, value);
537: }
538: }
539: }
540:
541: // handle the null start-tag, push null
542: void handleNullStartElement() {
543: stack.push(null);
544: }
545:
546: // returns the property value object from the content string
547: Object getContentValue(PropertyDescriptor pd, Class valueClass) {
548: Class editorClass = pd.getPropertyEditorClass();
549: PropertyEditor editor = null;
550: if (editorClass == null) {
551: editor = PropertyEditorManager.findEditor(valueClass);
552: } else {
553: try {
554: editor = (PropertyEditor) editorClass.newInstance();
555: } catch (IllegalAccessException ex) {
556: handler.propertyEditor(pd, ex);
557: return null;
558: } catch (InstantiationException ex) {
559: handler.propertyEditor(pd, ex);
560: return null;
561: } catch (NoSuchMethodError err) {
562: handler.propertyEditor(pd, err);
563: return null;
564: }
565: }
566: if (editor != null) {
567: editor.setAsText(new String(content));
568: return editor.getValue();
569: } else {
570: handler.propertyEditor(pd);
571: return null;
572: }
573: }
574:
575: // search the current property descriptor on the stack
576: PropertyDescriptor currentPropertyDescriptor() {
577: for (int i = stack.size() - 1; i >= 0; --i) {
578: Object obj = stack.elementAt(i);
579: if (obj instanceof PropertyDescriptor) {
580: return (PropertyDescriptor) obj;
581: }
582: }
583: return null;
584: }
585:
586: // returns the value of an attribute in the list, or null if any
587: String getAttributeValue(AttributeList list, String name) {
588: for (int i = 0; i < list.getLength(); ++i) {
589: if (list.getName(i).equals(name)) {
590: return list.getValue(i);
591: }
592: }
593: return null;
594: }
595: }
596:
597: /** An object that is pushed on the stack when an error occurs. */
598: private static final Object ERROR = new Object() {
599: };
600:
601: /**
602: * A SAX error handler for the SAX parser.
603: */
604: private class SAXErrorHandler implements org.xml.sax.ErrorHandler {
605:
606: public void error(SAXParseException e) throws SAXException {
607: // Nothing to do
608: }
609:
610: public void warning(SAXParseException e) throws SAXException {
611: showMessage("\tWarning: ", e);
612: }
613:
614: public void fatalError(SAXParseException e) throws SAXException {
615: showMessage("\tFatal Error: ", e);
616: }
617:
618: // Display a message, used by ErrorHandler
619: private void showMessage(String kind, SAXParseException e) {
620: System.err.println(" Line " + e.getLineNumber() + ":"
621: + e.getColumnNumber());
622: System.err.println("\t" + kind + ": " + e.getMessage());
623: if (e.getException() != null) {
624: e.getException().printStackTrace();
625: } else {
626: e.printStackTrace();
627: }
628: }
629: }
630:
631: /**
632: * A class used by tags that have a source attribute. Getting the
633: * value from bean cache using the source attribute is done in the
634: * end-tag method.
635: */
636: private static class SourceRef {
637: String source;
638:
639: SourceRef(String source) {
640: this .source = source;
641: }
642: }
643:
644: /**
645: * A class used by the valueArray start-tag to store the id of the
646: * array. The array will be added to the bean cache in the end-tag method.
647: */
648: private static class ValueArrayDecl {
649: String id;
650:
651: ValueArrayDecl(String id) {
652: this .id = id;
653: }
654: }
655:
656: /**
657: * A class used by the value start-tag to store the id and the class of a
658: * value. The value will be added to the bean cache in the end-tag method.
659: */
660: private static class ValueDecl {
661: String id;
662: Class valueClass;
663:
664: ValueDecl(String id, Class valueClass) {
665: this .id = id;
666: this .valueClass = valueClass;
667: }
668: }
669:
670: /**
671: * The handler interface for receiving no-fatal errors that may occur
672: * during the deserialization process. If an application needs to
673: * customize error handling, it must implement this interface and
674: * then instanciate the deserializer with correct arguments.
675: *
676: * <p>KBML deserializer calls this handler instead of throwing an
677: * exception, it is up to the application to throw an exception
678: * when needed.
679: *
680: * @author Thierry.Kormann@sophia.inria.fr
681: */
682: public interface ErrorHandler {
683:
684: // called by handleBeanStartElement
685:
686: /**
687: * Invoked when the bean can not be instanciated.
688: * @param className the name of the class
689: * @param ex the exception thrown
690: */
691: void instanciateBean(String className, IOException ex);
692:
693: /**
694: * Invoked when the bean can not be instanciated.
695: * @param className the name of the class
696: * @param ex the exception thrown
697: */
698: void instanciateBean(String className, ClassNotFoundException ex);
699:
700: /**
701: * Invoked when the bean can not be instanciated.
702: * @param className the name of the class
703: * @param ex the exception thrown
704: */
705: void instanciateBean(String className, IllegalAccessException ex);
706:
707: /**
708: * Invoked when the bean can not be instanciated.
709: * @param className the name of the class
710: * @param ex the exception thrown
711: */
712: void instanciateBean(String className, InstantiationException ex);
713:
714: /**
715: * Invoked when the bean can not be instanciated.
716: * @param className the name of the class
717: * @param err the error thrown
718: */
719: void instanciateBean(String className, NoSuchMethodError err);
720:
721: // called by handlePropertyStartElement
722:
723: /**
724: * Invoked when no property descriptor is available a specific property.
725: * @param bean the bean
726: * @param propertyName the name of the property
727: */
728: void propertyDescriptor(Object bean, String propertyName);
729:
730: /**
731: * Invoked when the introspector can not get the BeanInfo.
732: * @param bean the bean
733: * @param ex the exception thrown
734: */
735: void introspector(Object bean, IntrospectionException ex);
736:
737: // called by handlePropertyEndElement
738:
739: /**
740: * Invoked when no write method is found for a specific property.
741: * @param bean the bean
742: * @param pd the property descriptor
743: */
744: void writeMethod(Object bean, PropertyDescriptor pd);
745:
746: /**
747: * Invoked when a property value can not be set.
748: * @param bean the bean
749: * @param pd the property descriptor
750: * @param ex the exception thrown
751: */
752: void writeMethod(Object bean, PropertyDescriptor pd,
753: IllegalAccessException ex);
754:
755: /**
756: * Invoked when a property value can not be set.
757: * @param bean the bean
758: * @param pd the property descriptor
759: * @param ex the exception thrown
760: */
761: void writeMethod(Object bean, PropertyDescriptor pd,
762: InvocationTargetException ex);
763:
764: /**
765: * Invoked when the write method has been called with bad arguments.
766: * @param bean the bean
767: * @param pd the property descriptor
768: * @param ex the exception thrown
769: */
770: void writeMethod(Object bean, PropertyDescriptor pd,
771: IllegalArgumentException ex);
772:
773: // called by handleValueStartElement
774:
775: /**
776: * Invoked when the value can not be instanciated.
777: * @param className the name of the class
778: * @param ex the exception thrown
779: */
780: void instanciateValue(String className,
781: ClassNotFoundException ex);
782:
783: // called by getContentValue
784:
785: /**
786: * Invoked when a property editor can not be instanciated.
787: * @param pd the property descriptor
788: * @param ex the exception thrown
789: */
790: void propertyEditor(PropertyDescriptor pd,
791: IllegalAccessException ex);
792:
793: /**
794: * Invoked when a property editor can not be instanciated.
795: * @param pd the property descriptor
796: * @param ex the exception thrown
797: */
798: void propertyEditor(PropertyDescriptor pd,
799: InstantiationException ex);
800:
801: /**
802: * Invoked when a property editor can not be instanciated.
803: * @param pd the property descriptor
804: * @param err the error thrown
805: */
806: void propertyEditor(PropertyDescriptor pd, NoSuchMethodError err);
807:
808: /**
809: * Invoked when no property editor is found for a specific property.
810: * @param pd the property descriptor
811: */
812: void propertyEditor(PropertyDescriptor pd);
813: }
814: }
|