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