001    /*
002     * Copyright 2001-2004 The Apache Software Foundation.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package javax.xml.soap;
017    
018    /**
019     * An exception that signals that a SOAP exception has
020     *   occurred. A <CODE>SOAPException</CODE> object may contain a
021     *   <CODE>String</CODE> that gives the reason for the exception, an
022     *   embedded <CODE>Throwable</CODE> object, or both. This class
023     *   provides methods for retrieving reason messages and for
024     *   retrieving the embedded <CODE>Throwable</CODE> object.</P>
025     *
026     *   <P>Typical reasons for throwing a <CODE>SOAPException</CODE>
027     *   object are problems such as difficulty setting a header, not
028     *   being able to send a message, and not being able to get a
029     *   connection with the provider. Reasons for embedding a <CODE>
030     *   Throwable</CODE> object include problems such as input/output
031     *   errors or a parsing problem, such as an error in parsing a
032     *   header.
033     */
034    public class SOAPException extends Exception {
035    
036        /**
037         * Constructs a <CODE>SOAPException</CODE> object with no
038         * reason or embedded <CODE>Throwable</CODE> object.
039         */
040        public SOAPException() {
041            cause = null;
042        }
043    
044        /**
045         * Constructs a <CODE>SOAPException</CODE> object with the
046         * given <CODE>String</CODE> as the reason for the exception
047         * being thrown.
048         * @param  reason  a description of what caused
049         *     the exception
050         */
051        public SOAPException(String reason) {
052    
053            super(reason);
054    
055            cause = null;
056        }
057    
058        /**
059         * Constructs a <CODE>SOAPException</CODE> object with the
060         * given <CODE>String</CODE> as the reason for the exception
061         * being thrown and the given <CODE>Throwable</CODE> object as
062         * an embedded exception.
063         * @param  reason a description of what caused
064         *     the exception
065         * @param  cause  a <CODE>Throwable</CODE> object
066         *     that is to be embedded in this <CODE>SOAPException</CODE>
067         *     object
068         */
069        public SOAPException(String reason, Throwable cause) {
070    
071            super(reason);
072    
073            initCause(cause);
074        }
075    
076        /**
077         * Constructs a <CODE>SOAPException</CODE> object
078         * initialized with the given <CODE>Throwable</CODE>
079         * object.
080         * @param  cause  a <CODE>Throwable</CODE> object
081         *     that is to be embedded in this <CODE>SOAPException</CODE>
082         *     object
083         */
084        public SOAPException(Throwable cause) {
085    
086            super(cause.toString());
087    
088            initCause(cause);
089        }
090    
091        /**
092         * Returns the detail message for this <CODE>
093         *   SOAPException</CODE> object.
094         *
095         *   <P>If there is an embedded <CODE>Throwable</CODE> object,
096         *   and if the <CODE>SOAPException</CODE> object has no detail
097         *   message of its own, this method will return the detail
098         *   message from the embedded <CODE>Throwable</CODE>
099         *   object.</P>
100         * @return  the error or warning message for this <CODE>
101         *     SOAPException</CODE> or, if it has none, the message of
102         *     the embedded <CODE>Throwable</CODE> object, if there is
103         *     one
104         */
105        public String getMessage() {
106    
107            String s = super.getMessage();
108    
109            if ((s == null) && (cause != null)) {
110                return cause.getMessage();
111            } else {
112                return s;
113            }
114        }
115    
116        /**
117         * Returns the <CODE>Throwable</CODE> object embedded in
118         * this <CODE>SOAPException</CODE> if there is one. Otherwise,
119         * this method returns <CODE>null</CODE>.
120         * @return  the embedded <CODE>Throwable</CODE> object or <CODE>
121         *     null</CODE> if there is none
122         */
123        public Throwable getCause() {
124            return cause;
125        }
126    
127        /**
128         * Initializes the <CODE>cause</CODE> field of this <CODE>
129         *   SOAPException</CODE> object with the given <CODE>
130         *   Throwable</CODE> object.
131         *
132         *   <P>This method can be called at most once. It is generally
133         *   called from within the constructor or immediately after the
134         *   constructor has returned a new <CODE>SOAPException</CODE>
135         *   object. If this <CODE>SOAPException</CODE> object was
136         *   created with the constructor {@link #SOAPException(java.lang.Throwable) SOAPException(java.lang.Throwable)}
137         *   or {@link #SOAPException(java.lang.String, java.lang.Throwable) SOAPException(java.lang.String, java.lang.Throwable)}, meaning
138         *   that its <CODE>cause</CODE> field already has a value, this
139         *   method cannot be called even once.
140         *
141         * @param cause  the <CODE>Throwable</CODE>
142         *     object that caused this <CODE>SOAPException</CODE> object
143         *     to be thrown. The value of this parameter is saved for
144         *     later retrieval by the <A href=
145         *     "../../../javax/xml/soap/SOAPException.html#getCause()">
146         *     <CODE>getCause()</CODE></A> method. A <TT>null</TT> value
147         *     is permitted and indicates that the cause is nonexistent
148         *     or unknown.
149         * @return a reference to this <CODE>SOAPException</CODE>
150         *     instance
151         * @throws java.lang.IllegalArgumentException if
152         *     <CODE>cause</CODE> is this <CODE>Throwable</CODE> object.
153         *     (A <CODE>Throwable</CODE> object cannot be its own
154         *     cause.)
155         * @throws java.lang.IllegalStateException if this <CODE>
156         *     SOAPException</CODE> object was created with {@link #SOAPException(java.lang.Throwable) SOAPException(java.lang.Throwable)}
157         *   or {@link #SOAPException(java.lang.String, java.lang.Throwable) SOAPException(java.lang.String, java.lang.Throwable)}, or this
158         *     method has already been called on this <CODE>
159         *     SOAPException</CODE> object
160         */
161        public synchronized Throwable initCause(Throwable cause) {
162    
163            if (this.cause != null) {
164                throw new IllegalStateException("Can't override cause");
165            }
166    
167            if (cause == this) {
168                throw new IllegalArgumentException("Self-causation not permitted");
169            } else {
170                this.cause = cause;
171    
172                return this;
173            }
174        }
175    
176        private Throwable cause;
177    }