001/** 002 * 003 * Copyright 2003-2007 Jive Software. 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.jivesoftware.smack; 019 020import org.jivesoftware.smack.packet.Nonza; 021import org.jivesoftware.smack.packet.Stanza; 022import org.jivesoftware.smack.packet.StreamError; 023import org.jivesoftware.smack.packet.XMPPError; 024 025import org.jxmpp.jid.Jid; 026 027/** 028 * A generic exception that is thrown when an error occurs performing an 029 * XMPP operation. XMPP servers can respond to error conditions with an error code 030 * and textual description of the problem, which are encapsulated in the XMPPError 031 * class. When appropriate, an XMPPError instance is attached instances of this exception.<p> 032 * 033 * When a stream error occurred, the server will send a stream error to the client before 034 * closing the connection. Stream errors are unrecoverable errors. When a stream error 035 * is sent to the client an XMPPException will be thrown containing the StreamError sent 036 * by the server. 037 * 038 * @see XMPPError 039 * @author Matt Tucker 040 */ 041public abstract class XMPPException extends Exception { 042 private static final long serialVersionUID = 6881651633890968625L; 043 044 045 /** 046 * Creates a new XMPPException. 047 */ 048 protected XMPPException() { 049 super(); 050 } 051 052 /** 053 * Creates a new XMPPException with a description of the exception. 054 * 055 * @param message description of the exception. 056 */ 057 protected XMPPException(String message) { 058 super(message); 059 } 060 061 /** 062 * Creates a new XMPPException with a description of the exception and the 063 * Throwable that was the root cause of the exception. 064 * 065 * @param message a description of the exception. 066 * @param wrappedThrowable the root cause of the exception. 067 */ 068 protected XMPPException(String message, Throwable wrappedThrowable) { 069 super(message, wrappedThrowable); 070 } 071 072 public static class XMPPErrorException extends XMPPException { 073 /** 074 * 075 */ 076 private static final long serialVersionUID = 212790389529249604L; 077 private final XMPPError error; 078 private final Stanza stanza; 079 080 /** 081 * Creates a new XMPPErrorException with the given builder. 082 * 083 * @param xmppErrorBuilder 084 * @deprecated Use {@link #XMPPErrorException(Stanza, XMPPError)} instead. 085 */ 086 @Deprecated 087 public XMPPErrorException(XMPPError.Builder xmppErrorBuilder) { 088 this(null, xmppErrorBuilder.build()); 089 } 090 091 /** 092 * Creates a new XMPPErrorException with the XMPPError that was the root case of the exception. 093 * 094 * @param stanza stanza that contained the exception. 095 * @param error the root cause of the exception. 096 */ 097 public XMPPErrorException(Stanza stanza, XMPPError error) { 098 super(); 099 this.error = error; 100 this.stanza = stanza; 101 } 102 103 /** 104 * Returns the XMPPError associated with this exception, or <tt>null</tt> if there isn't 105 * one. 106 * 107 * @return the XMPPError associated with this exception. 108 */ 109 public XMPPError getXMPPError() { 110 return error; 111 } 112 113 @Override 114 public String getMessage() { 115 StringBuilder sb = new StringBuilder(); 116 117 if (stanza != null) { 118 Jid from = stanza.getFrom(); 119 if (from != null) { 120 sb.append("XMPP error reply received from " + from + ": "); 121 } 122 } 123 124 sb.append(error); 125 126 return sb.toString(); 127 } 128 129 public static void ifHasErrorThenThrow(Stanza packet) throws XMPPErrorException { 130 XMPPError xmppError = packet.getError(); 131 if (xmppError != null) { 132 throw new XMPPErrorException(packet, xmppError); 133 } 134 } 135 } 136 137 public static class FailedNonzaException extends XMPPException { 138 139 /** 140 * 141 */ 142 private static final long serialVersionUID = 1L; 143 144 private final XMPPError.Condition condition; 145 146 private final Nonza nonza; 147 148 public FailedNonzaException(Nonza nonza, XMPPError.Condition condition) { 149 this.condition = condition; 150 this.nonza = nonza; 151 } 152 153 public XMPPError.Condition getCondition() { 154 return condition; 155 } 156 157 public Nonza getNonza() { 158 return nonza; 159 } 160 } 161 162 public static class StreamErrorException extends XMPPException { 163 /** 164 * 165 */ 166 private static final long serialVersionUID = 3400556867134848886L; 167 private final StreamError streamError; 168 169 /** 170 * Creates a new XMPPException with the stream error that was the root case of the 171 * exception. When a stream error is received from the server then the underlying connection 172 * will be closed by the server. 173 * 174 * @param streamError the root cause of the exception. 175 */ 176 public StreamErrorException(StreamError streamError) { 177 super(streamError.getCondition().toString() 178 + " You can read more about the meaning of this stream error at http://xmpp.org/rfcs/rfc6120.html#streams-error-conditions\n" 179 + streamError.toString()); 180 this.streamError = streamError; 181 } 182 183 /** 184 * Returns the StreamError associated with this exception. The underlying TCP connection is 185 * closed by the server after sending the stream error to the client. 186 * 187 * @return the StreamError associated with this exception. 188 */ 189 public StreamError getStreamError() { 190 return streamError; 191 } 192 193 } 194}