1 /*
   2  * Copyright (c) 1997, 2012, 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 package com.sun.xml.internal.messaging.saaj;
  27 
  28 import java.io.PrintStream;
  29 import java.io.PrintWriter;
  30 
  31 import javax.xml.soap.SOAPException;
  32 
  33 /**
  34  * An exception that signals that a SOAP exception has occurred. A
  35  * <code>SOAPExceptionImpl</code> object may contain a <code>String</code>
  36  * that gives the reason for the exception, an embedded
  37  * <code>Throwable</code> object, or both. This class provides methods
  38  * for retrieving reason messages and for retrieving the embedded
  39  * <code>Throwable</code> object.
  40  *
  41  * <P> Typical reasons for throwing a <code>SOAPExceptionImpl</code>
  42  * object are problems such as difficulty setting a header, not being
  43  * able to send a message, and not being able to get a connection with
  44  * the provider.  Reasons for embedding a <code>Throwable</code>
  45  * object include problems such as input/output errors or a parsing
  46  * problem, such as an error in parsing a header.
  47  */
  48 public class SOAPExceptionImpl extends SOAPException {
  49     private Throwable cause;
  50 
  51     /**
  52      * Constructs a <code>SOAPExceptionImpl</code> object with no
  53      * reason or embedded <code>Throwable</code> object.
  54      */
  55     public SOAPExceptionImpl() {
  56         super();
  57         this.cause = null;
  58     }
  59 
  60     /**
  61      * Constructs a <code>SOAPExceptionImpl</code> object with the given
  62      * <code>String</code> as the reason for the exception being thrown.
  63      *
  64      * @param reason a description of what caused the exception
  65      */
  66     public SOAPExceptionImpl(String reason) {
  67         super(reason);
  68         this.cause = null;
  69     }
  70 
  71     /**
  72      * Constructs a <code>SOAPExceptionImpl</code> object with the given
  73      * <code>String</code> as the reason for the exception being thrown
  74      * and the given <code>Throwable</code> object as an embedded
  75      * exception.
  76      *
  77      * @param reason a description of what caused the exception
  78      * @param cause a <code>Throwable</code> object that is to
  79      *        be embedded in this <code>SOAPExceptionImpl</code> object
  80      */
  81     public SOAPExceptionImpl(String reason, Throwable cause) {
  82        super (reason);
  83        initCause(cause);
  84     }
  85 
  86     /**
  87      * Constructs a <code>SOAPExceptionImpl</code> object initialized
  88      * with the given <code>Throwable</code> object.
  89      */
  90     public SOAPExceptionImpl(Throwable cause) {
  91         super (cause.toString());
  92         initCause(cause);
  93     }
  94 
  95     /**
  96      * Returns the detail message for this <code>SOAPExceptionImpl</code>
  97      * object.
  98      * <P>
  99      * If there is an embedded <code>Throwable</code> object, and if the
 100      * <code>SOAPExceptionImpl</code> object has no detail message of its
 101      * own, this method will return the detail message from the embedded
 102      * <code>Throwable</code> object.
 103      *
 104      * @return the error or warning message for this
 105      *         <code>SOAPExceptionImpl</code> or, if it has none, the
 106      *         message of the embedded <code>Throwable</code> object,
 107      *         if there is one
 108      */
 109     public String getMessage() {
 110         String message = super.getMessage ();
 111         if (message == null && cause != null) {
 112             return cause.getMessage();
 113         } else {
 114             return message;
 115         }
 116     }
 117 
 118     /**
 119      * Returns the <code>Throwable</code> object embedded in this
 120      * <code>SOAPExceptionImpl</code> if there is one. Otherwise, this method
 121      * returns <code>null</code>.
 122      *
 123      * @return the embedded <code>Throwable</code> object or <code>null</code>
 124      *         if there is none
 125      */
 126 
 127     public Throwable getCause() {
 128         return cause;
 129     }
 130 
 131     /**
 132      * Initializes the <code>cause</code> field of this <code>SOAPExceptionImpl</code>
 133      * object with the given <code>Throwable</code> object.
 134      * <P>
 135      * This method can be called at most once.  It is generally called from
 136      * within the constructor or immediately after the constructor has
 137      * returned a new <code>SOAPExceptionImpl</code> object.
 138      * If this <code>SOAPExceptionImpl</code> object was created with the
 139      * constructor {@link #SOAPExceptionImpl(Throwable)} or
 140      * {@link #SOAPExceptionImpl(String,Throwable)}, meaning that its
 141      * <code>cause</code> field already has a value, this method cannot be
 142      * called even once.
 143      *
 144      * @param  cause the <code>Throwable</code> object that caused this
 145      *         <code>SOAPExceptionImpl</code> object to be thrown.  The value of this
 146      *         parameter is saved for later retrieval by the
 147      *         {@link #getCause()} method.  A {@code null} value is
 148      *         permitted and indicates that the cause is nonexistent or
 149      *         unknown.
 150      * @return  a reference to this <code>SOAPExceptionImpl</code> instance
 151      * @throws IllegalArgumentException if <code>cause</code> is this
 152      *         <code>Throwable</code> object.  (A <code>Throwable</code> object
 153      *         cannot be its own cause.)
 154      * @throws IllegalStateException if this <code>SOAPExceptionImpl</code> object
 155      *         was created with {@link #SOAPExceptionImpl(Throwable)} or
 156      *         {@link #SOAPExceptionImpl(String,Throwable)}, or this
 157      *         method has already been called on this <code>SOAPExceptionImpl</code>
 158      *         object
 159      */
 160     public synchronized Throwable initCause(Throwable cause)
 161     {
 162         if(this.cause != null) {
 163             throw new IllegalStateException("Can't override cause");
 164         }
 165         if(cause == this) {
 166             throw new IllegalArgumentException("Self-causation not permitted");
 167         }
 168         this.cause = cause;
 169 
 170         return this;
 171     }
 172 
 173     public void printStackTrace() {
 174         super.printStackTrace();
 175         if (cause != null) {
 176             System.err.println("\nCAUSE:\n");
 177             cause.printStackTrace();
 178         }
 179     }
 180 
 181     public void printStackTrace(PrintStream s) {
 182         super.printStackTrace(s);
 183         if (cause != null) {
 184             s.println("\nCAUSE:\n");
 185             cause.printStackTrace(s);
 186         }
 187     }
 188 
 189     public void printStackTrace(PrintWriter s) {
 190         super.printStackTrace(s);
 191         if (cause != null) {
 192             s.println("\nCAUSE:\n");
 193             cause.printStackTrace(s);
 194         }
 195     }
 196 }