1 /*
   2  * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 // SAX exception class.
  27 // http://www.saxproject.org
  28 // No warranty; no copyright -- use this as you will.
  29 // $Id: SAXException.java,v 1.3 2004/11/03 22:55:32 jsuttor Exp $
  30 
  31 package org.xml.sax;
  32 
  33 import java.io.IOException;
  34 import java.io.InvalidClassException;
  35 import java.io.ObjectInputStream;
  36 import java.io.ObjectOutputStream;
  37 import java.io.ObjectStreamField;
  38 
  39 /**
  40  * Encapsulate a general SAX error or warning.
  41  *
  42  * <blockquote>
  43  * <em>This module, both source code and documentation, is in the
  44  * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
  45  * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
  46  * for further information.
  47  * </blockquote>
  48  *
  49  * <p>This class can contain basic error or warning information from
  50  * either the XML parser or the application: a parser writer or
  51  * application writer can subclass it to provide additional
  52  * functionality.  SAX handlers may throw this exception or
  53  * any exception subclassed from it.</p>
  54  *
  55  * <p>If the application needs to pass through other types of
  56  * exceptions, it must wrap those exceptions in a SAXException
  57  * or an exception derived from a SAXException.</p>
  58  *
  59  * <p>If the parser or application needs to include information about a
  60  * specific location in an XML document, it should use the
  61  * {@link org.xml.sax.SAXParseException SAXParseException} subclass.</p>
  62  *
  63  * @since 1.4, SAX 1.0
  64  * @author David Megginson
  65  * @version 2.0.1 (sax2r2)
  66  * @see org.xml.sax.SAXParseException
  67  */
  68 public class SAXException extends Exception {
  69 
  70 
  71     /**
  72      * Create a new SAXException.
  73      */
  74     public SAXException ()
  75     {
  76         super();
  77     }
  78 
  79 
  80     /**
  81      * Create a new SAXException.
  82      *
  83      * @param message The error or warning message.
  84      */
  85     public SAXException (String message) {
  86         super(message);
  87     }
  88 
  89 
  90     /**
  91      * Create a new SAXException wrapping an existing exception.
  92      *
  93      * <p>The existing exception will be embedded in the new
  94      * one, and its message will become the default message for
  95      * the SAXException.</p>
  96      *
  97      * @param e The exception to be wrapped in a SAXException.
  98      */
  99     public SAXException (Exception e)
 100     {
 101         super(e);
 102     }
 103 
 104 
 105     /**
 106      * Create a new SAXException from an existing exception.
 107      *
 108      * <p>The existing exception will be embedded in the new
 109      * one, but the new exception will have its own message.</p>
 110      *
 111      * @param message The detail message.
 112      * @param e The exception to be wrapped in a SAXException.
 113      */
 114     public SAXException (String message, Exception e)
 115     {
 116         super(message, e);
 117     }
 118 
 119 
 120     /**
 121      * Return a detail message for this exception.
 122      *
 123      * <p>If there is an embedded exception, and if the SAXException
 124      * has no detail message of its own, this method will return
 125      * the detail message from the embedded exception.</p>
 126      *
 127      * @return The error or warning message.
 128      */
 129     public String getMessage ()
 130     {
 131         String message = super.getMessage();
 132         Throwable cause = super.getCause();
 133 
 134         if (message == null && cause != null) {
 135             return cause.getMessage();
 136         } else {
 137             return message;
 138         }
 139     }
 140 
 141     /**
 142      * Return the embedded exception, if any.
 143      *
 144      * @return The embedded exception, or null if there is none.
 145      */
 146     public Exception getException ()
 147     {
 148         return getExceptionInternal();
 149     }
 150 
 151     /**
 152      * Return the cause of the exception
 153      *
 154      * @return Return the cause of the exception
 155      */
 156     public Throwable getCause() {
 157         return super.getCause();
 158     }
 159 
 160     /**
 161      * Override toString to pick up any embedded exception.
 162      *
 163      * @return A string representation of this exception.
 164      */
 165     public String toString ()
 166     {
 167         Throwable exception = super.getCause();
 168         if (exception != null) {
 169             return super.toString() + "\n" + exception.toString();
 170         } else {
 171             return super.toString();
 172         }
 173     }
 174 
 175 
 176 
 177     //////////////////////////////////////////////////////////////////////
 178     // Internal state.
 179     //////////////////////////////////////////////////////////////////////
 180 
 181     private static final ObjectStreamField[] serialPersistentFields = {
 182         new ObjectStreamField( "exception", Exception.class )
 183     };
 184 
 185     /**
 186      * Writes "exception" field to the stream.
 187      *
 188      * @param out stream used for serialization.
 189      * @throws IOException thrown by <code>ObjectOutputStream</code>
 190      */
 191     private void writeObject(ObjectOutputStream out)
 192             throws IOException {
 193         ObjectOutputStream.PutField fields = out.putFields();
 194         fields.put("exception", getExceptionInternal());
 195         out.writeFields();
 196     }
 197 
 198     /**
 199      * Reads the "exception" field from the stream.
 200      * And initializes the "exception" if it wasn't
 201      * done before.
 202      *
 203      * @param in stream used for deserialization
 204      * @throws IOException            thrown by <code>ObjectInputStream</code>
 205      * @throws ClassNotFoundException thrown by <code>ObjectInputStream</code>
 206      */
 207     private void readObject(ObjectInputStream in)
 208             throws IOException, ClassNotFoundException {
 209         ObjectInputStream.GetField fields = in.readFields();
 210         Exception exception = (Exception) fields.get("exception", null);
 211         Throwable superCause = super.getCause();
 212 
 213         // if super.getCause() and 'exception' fields present then always use
 214         // getCause() value. Otherwise, use 'exception' to initialize cause
 215         if (superCause == null && exception != null) {
 216             try {
 217                 super.initCause(exception);
 218             } catch (IllegalStateException e) {
 219                 throw new InvalidClassException("Inconsistent state: two causes");
 220             }
 221         }
 222     }
 223 
 224     // Internal method to guard against overriding of public getException
 225     // method by SAXException subclasses
 226     private Exception getExceptionInternal() {
 227         Throwable cause = super.getCause();
 228         if (cause instanceof Exception) {
 229             return (Exception) cause;
 230         } else {
 231             return null;
 232         }
 233     }
 234 
 235     // Added serialVersionUID to preserve binary compatibility
 236     static final long serialVersionUID = 583241635256073760L;
 237 }
 238 
 239 // end of SAXException.java