[jdom-interest] SAXBuilder exception patches

Elliotte Rusty Harold elharo at metalab.unc.edu
Wed Apr 10 12:07:55 PDT 2002


I've attached patches for the four classes affected by the decision to 
allow build() to throw IOException. I've made separate patch files for 
each of the classes because my last mega-patch had troubles being 
applied. The four files are:

SAXBuilder
SAXHandler
JDOMResult
TestVerifier

All the tests that ran before still run after these four patches are 
applied. This is going to affect a lot of client code, but in my initial 
tests not as much as I originally expected.

The basic idea of these patches is to rationalize the excepiton 
throwing. This patch does several things:

1. Allows IOExceptions to propagate unchanged from the builder.
2. Converts all SAXExceptions to JDOMExceptions
3. Removes a number of "throws Exception" and "throws IOException" 
clauses where no exception was being thrown.
4. Changes some "throws Exception" and "throws IOException" clauses to 
"throws JDOMException"
5. Allows unexpected runtime exceptions (e.g. NullPointerException) to 
propagate unchanged.

I think this makes sense. The basic idea is that SAXBuilder should throw 
an IOException for an I/O error, a JDOMException for an XML problem, and 
that unexpected runtime exceptions should not be hidden. I fully expect 
that this will break existing code, but the sooner we do it the less 
pain it will cause. As always more testing is appreciated.


-- 
+-----------------------+------------------------+-------------------+
| Elliotte Rusty Harold | elharo at metalab.unc.edu | Writer/Programmer |
+-----------------------+------------------------+-------------------+ 
|           The XML Bible, 2nd Edition (IDG Books, 2001)             |
|             http://www.cafeconleche.org/books/bible2/              |
|   http://www.amazon.com/exec/obidos/ISBN=0764547607/cafeaulaitA/   |
+----------------------------------+---------------------------------+
|  Read Cafe au Lait for Java News:   http://www.cafeaulait.org/     | 
|  Read Cafe con Leche for XML News:  http://www.cafeconleche.org/   |
+----------------------------------+---------------------------------+


-------------- next part --------------
Index: src/java/org/jdom/input/SAXHandler.java
===================================================================
RCS file: /home/cvspublic/jdom/src/java/org/jdom/input/SAXHandler.java,v
retrieving revision 1.39
diff -d -u -r1.39 SAXHandler.java
--- src/java/org/jdom/input/SAXHandler.java	2002/03/15 05:36:48	1.39
+++ src/java/org/jdom/input/SAXHandler.java	2002/04/11 03:08:28
@@ -197,12 +197,11 @@
      * </p>
      *
      * @param document <code>Document</code> being parsed.
-     * @throws IOException when errors occur.
      *
      * @deprecated Deprecated in beta7, use SAXHandler() instead and let
      * SAXHandler create the Document, then retrieve it with getDocument()
      */
-    public SAXHandler(Document document) throws IOException {
+    public SAXHandler(Document document) {
         this(new DefaultJDOMFactory());
         this.document = document;
     }
@@ -214,9 +213,8 @@
      * using the default factory.
      * </p>
      *
-     * @throws IOException when errors occur.
      */
-    public SAXHandler() throws IOException {
+    public SAXHandler() {
         this((JDOMFactory)null);
     }
 
@@ -229,9 +227,8 @@
      *
      * @param factory <code>JDOMFactory</code> to be used for constructing
      * objects
-     * @throws IOException when errors occur.
      */
-    public SAXHandler(JDOMFactory factory) throws IOException {
+    public SAXHandler(JDOMFactory factory) {
         if (factory != null) {
             this.factory = factory;
         } else {
-------------- next part --------------
Index: src/java/org/jdom/input/SAXBuilder.java
===================================================================
RCS file: /home/cvspublic/jdom/src/java/org/jdom/input/SAXBuilder.java,v
retrieving revision 1.64
diff -d -u -r1.64 SAXBuilder.java
--- src/java/org/jdom/input/SAXBuilder.java	2002/02/26 04:10:33	1.64
+++ src/java/org/jdom/input/SAXBuilder.java	2002/04/11 03:09:28
@@ -1,6 +1,6 @@
 /*-- 
 
- $Id: SAXBuilder.java,v 1.64 2002/02/26 04:10:33 jhunter Exp $
+ $Id: SAXBuilder.java,v 1.65 2002/04/10 04:10:33 jhunter Exp $
 
  Copyright (C) 2000 Brett McLaughlin & Jason Hunter.
  All rights reserved.
@@ -81,7 +81,7 @@
  * @author Dan Schaffer
  * @author Philip Nelson
  * @author Alex Rosen
- * @version $Revision: 1.64 $, $Date: 2002/02/26 04:10:33 $
+ * @version $Revision: 1.65 $, $Date: 2002/02/26 04:10:33 $
  */
 public class SAXBuilder {
 
@@ -322,8 +322,11 @@
      * @param in <code>InputSource</code> to read from.
      * @return <code>Document</code> - resultant Document object.
      * @throws JDOMException when errors occur in parsing.
+     * @throws IOException when an I/O error prevents a document
+     *         from being fully parsed.
      */
-    public Document build(InputSource in) throws JDOMException {
+    public Document build(InputSource in) 
+     throws JDOMException, IOException {
         SAXHandler contentHandler = null;
 
         try {
@@ -355,24 +358,21 @@
 
             return contentHandler.getDocument();
         }
-        catch (Exception e) {
-            if (e instanceof SAXParseException) {
-                SAXParseException p = (SAXParseException)e;
-                String systemId = p.getSystemId();
-                if (systemId != null) {
-                    throw new JDOMException("Error on line " + 
-                              p.getLineNumber() + " of document "
-                              + systemId, e);
-                } else {
-                    throw new JDOMException("Error on line " +
-                              p.getLineNumber(), e);
-                }
-            } else if (e instanceof JDOMException) {
-                throw (JDOMException)e;
-            } else {
-                throw new JDOMException("Error in building", e);
-            }
+        catch (SAXParseException e) {
+          String systemId = e.getSystemId();
+          if (systemId != null) {
+              throw new JDOMException("Error on line " + 
+                e.getLineNumber() + " of document " + systemId, 
+                e);
+          } else {
+              throw new JDOMException("Error on line " +
+                              e.getLineNumber(), e);
+          }
         }
+        catch (SAXException e) {
+            throw new JDOMException("Error in building: " + 
+                e.getMessage(), e);
+        }
         finally {
             // Explicitly nullify the handler to encourage GC
             // It's a stack var so this shouldn't be necessary, but it
@@ -385,8 +385,10 @@
      * <p>
      * This creates the SAXHandler that will be used to build the Document.
      * </p>
+     *
+     * @return <code>SAXHandler</code> - resultant SAXHandler object.
      */
-    protected SAXHandler createContentHandler() throws Exception {
+    protected SAXHandler createContentHandler() {
         SAXHandler contentHandler = new SAXHandler(factory);
         return contentHandler;
     }
@@ -401,8 +403,7 @@
      * setIgnoringElementContentWhitespace().
      * </p>
      */
-    protected void configureContentHandler(SAXHandler contentHandler) 
-                    throws Exception {
+    protected void configureContentHandler(SAXHandler contentHandler) {
         // Setup pass through behavior
         contentHandler.setExpandEntities(expand);
         contentHandler.setIgnoringElementContentWhitespace(ignoringWhite);
@@ -419,13 +420,20 @@
      * the Xerces parser). Subclasses may override this method to determine
      * the parser to use in a different way.
      * </p>
+     *
+     * @return <code>XMLReader</code> - resultant XMLReader object.
      */
-    protected XMLReader createParser() throws Exception {
+    protected XMLReader createParser() throws JDOMException {
         XMLReader parser = null;
         if (saxDriverClass != null) {
             // The user knows that they want to use a particular class
-            parser = XMLReaderFactory.createXMLReader(saxDriverClass);
-            // System.out.println("using specific " + saxDriverClass);
+            try {
+              parser = XMLReaderFactory.createXMLReader(saxDriverClass);
+              // System.out.println("using specific " + saxDriverClass);
+            }
+            catch (SAXException e) {
+              throw new JDOMException("Could not load " + saxDriverClass, e); 
+            }
         } else {
             // Try using JAXP...
             // Note we need JAXP 1.1, and if JAXP 1.0 is all that's
@@ -474,9 +482,15 @@
         // Check to see if we got a parser yet, if not, try to use a
         // hard coded default
         if (parser == null) {
-            parser = XMLReaderFactory.createXMLReader(DEFAULT_SAX_DRIVER);
-            // System.out.println("using default " + DEFAULT_SAX_DRIVER);
-            saxDriverClass = parser.getClass().getName();
+            try {
+                parser = XMLReaderFactory.createXMLReader(DEFAULT_SAX_DRIVER);
+                // System.out.println("using default " + DEFAULT_SAX_DRIVER);
+                saxDriverClass = parser.getClass().getName();
+            }
+            catch (SAXException e) {
+                throw new JDOMException("Could not load default SAX parser: "
+                  + DEFAULT_SAX_DRIVER, e); 
+            }
         }
 
         return parser;
@@ -496,7 +510,7 @@
      * </p>
      */
     protected void configureParser(XMLReader parser, SAXHandler contentHandler)
-                    throws Exception {
+        throws JDOMException {
 
         // Setup SAX handlers.
 
@@ -668,8 +682,11 @@
      * @param in <code>InputStream</code> to read from.
      * @return <code>Document</code> - resultant Document object.
      * @throws JDOMException when errors occur in parsing.
+     * @throws IOException when an I/O error prevents a document
+     *         from being fully parsed.
      */
-    public Document build(InputStream in) throws JDOMException {
+    public Document build(InputStream in) 
+     throws JDOMException, IOException {
         return build(new InputSource(in));
     }
 
@@ -682,8 +699,11 @@
      * @param file <code>File</code> to read from.
      * @return <code>Document</code> - resultant Document object.
      * @throws JDOMException when errors occur in parsing.
+     * @throws IOException when an I/O error prevents a document
+     *         from being fully parsed.
      */
-    public Document build(File file) throws JDOMException {
+    public Document build(File file) 
+        throws JDOMException, IOException {
         try {
             URL url = fileToURL(file);
             return build(url);
@@ -701,8 +721,11 @@
      * @param url <code>URL</code> to read from.
      * @return <code>Document</code> - resultant Document object.
      * @throws JDOMException when errors occur in parsing.
+     * @throws IOException when an I/O error prevents a document
+     *         from being fully parsed.
      */
-    public Document build(URL url) throws JDOMException {
+    public Document build(URL url) 
+        throws JDOMException, IOException {
         String systemID = url.toExternalForm();
         return build(new InputSource(systemID));
     }
@@ -717,9 +740,11 @@
      * @param systemId base for resolving relative URIs
      * @return <code>Document</code> - resultant Document object.
      * @throws JDOMException when errors occur in parsing.
+     * @throws IOException when an I/O error prevents a document
+     *         from being fully parsed.
      */
     public Document build(InputStream in, String systemId)
-        throws JDOMException {
+        throws JDOMException, IOException {
 
         InputSource src = new InputSource(in);
         src.setSystemId(systemId);
@@ -735,8 +760,11 @@
      * @param in <code>Reader</code> to read from.
      * @return <code>Document</code> - resultant Document object.
      * @throws JDOMException when errors occur in parsing.
+     * @throws IOException when an I/O error prevents a document
+     *         from being fully parsed.
      */
-    public Document build(Reader characterStream) throws JDOMException {
+    public Document build(Reader characterStream) 
+        throws JDOMException, IOException {
         return build(new InputSource(characterStream));
     }
 
@@ -750,9 +778,11 @@
      * @param systemId base for resolving relative URIs
      * @return <code>Document</code> - resultant Document object.
      * @throws JDOMException when errors occur in parsing.
+     * @throws IOException when an I/O error prevents a document
+     *         from being fully parsed.
      */
     public Document build(Reader characterStream, String SystemId)
-        throws JDOMException {
+        throws JDOMException, IOException {
 
         InputSource src = new InputSource(characterStream);
         src.setSystemId(SystemId);
@@ -767,8 +797,11 @@
      * @param systemId URI for the input
      * @return <code>Document</code> - resultant Document object.
      * @throws JDOMException when errors occur in parsing.
+     * @throws IOException when an I/O error prevents a document
+     *         from being fully parsed.
      */
-    public Document build(String systemId) throws JDOMException {
+    public Document build(String systemId) 
+        throws JDOMException, IOException {
         return build(new InputSource(systemId));
     }
 
-------------- next part --------------
Index: src/java/org/jdom/transform/JDOMResult.java
===================================================================
RCS file: /home/cvspublic/jdom/src/java/org/jdom/transform/JDOMResult.java,v
retrieving revision 1.5
diff -d -u -r1.5 JDOMResult.java
--- src/java/org/jdom/transform/JDOMResult.java	2002/01/08 09:17:10	1.5
+++ src/java/org/jdom/transform/JDOMResult.java	2002/04/11 03:10:07
@@ -253,7 +253,6 @@
      * @see    SAXHandler
      */
     public void startDocument() throws SAXException {
-      try {
         // Reset any previously set result document.
         setDocument(null);
 
@@ -266,10 +265,6 @@
 
         // And propagate event.
         super.startDocument();
-      }
-      catch (IOException e) {
-        throw new SAXException("SAXHandler allocation failure", e);
-      }
     }
 
     /**
-------------- next part --------------
Index: src/java/org/jdom/test/cases/TestVerifier.java
===================================================================
RCS file: /home/cvspublic/jdom-test/src/java/org/jdom/test/cases/TestVerifier.java,v
retrieving revision 1.3
diff -d -u -r1.3 TestVerifier.java
--- src/java/org/jdom/test/cases/TestVerifier.java	2001/06/26 03:58:14	1.3
+++ src/java/org/jdom/test/cases/TestVerifier.java	2002/04/11 03:11:37
@@ -291,7 +291,7 @@
 	/**
 	 * This method is called before a test is executed.
 	 */
-	public void setUp() throws FileNotFoundException, JDOMException {
+	public void setUp() throws FileNotFoundException, JDOMException, IOException {
 		
 		// get the ranges of valid characters from the xmlchars.xml resource
 		resourceRoot = rb.getString("test.resourceRoot");


More information about the jdom-interest mailing list