001/** 002 * 003 * Copyright 2014-2015 Florian Schmaus 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 */ 017package org.jivesoftware.smack; 018 019import java.util.ArrayList; 020import java.util.List; 021 022import org.jivesoftware.smack.filter.StanzaFilter; 023import org.jivesoftware.smack.util.dns.HostAddress; 024import org.jxmpp.jid.Jid; 025 026/** 027 * Smack uses SmackExceptions for errors that are not defined by any XMPP specification. 028 * 029 * @author Florian Schmaus 030 */ 031public class SmackException extends Exception { 032 033 /** 034 * 035 */ 036 private static final long serialVersionUID = 1844674365368214457L; 037 038 /** 039 * Creates a new SmackException with the Throwable that was the root cause of the exception. 040 * 041 * @param wrappedThrowable the root cause of the exception. 042 */ 043 public SmackException(Throwable wrappedThrowable) { 044 super(wrappedThrowable); 045 } 046 047 public SmackException(String message) { 048 super(message); 049 } 050 051 public SmackException(String message, Throwable wrappedThrowable) { 052 super(message, wrappedThrowable); 053 } 054 055 protected SmackException() { 056 } 057 058 /** 059 * Exception thrown always when there was no response to an request within the stanza(/packet) reply timeout of the used 060 * connection instance. You can modify (e.g. increase) the stanza(/packet) reply timeout with 061 * {@link XMPPConnection#setReplyTimeout(long)}. 062 */ 063 public static final class NoResponseException extends SmackException { 064 /** 065 * 066 */ 067 private static final long serialVersionUID = -6523363748984543636L; 068 069 private final StanzaFilter filter; 070 071 private NoResponseException(String message) { 072 this(message, null); 073 } 074 075 private NoResponseException(String message, StanzaFilter filter) { 076 super(message); 077 this.filter = filter; 078 } 079 080 /** 081 * Get the filter that was used to collect the response. 082 * 083 * @return the used filter or <code>null</code>. 084 */ 085 public StanzaFilter getFilter() { 086 return filter; 087 } 088 089 public static NoResponseException newWith(XMPPConnection connection, String waitingFor) { 090 final StringBuilder sb = getWaitingFor(connection); 091 sb.append(" While waiting for ").append(waitingFor); 092 return new NoResponseException(sb.toString()); 093 } 094 095 public static NoResponseException newWith(XMPPConnection connection, 096 StanzaCollector collector) { 097 return newWith(connection, collector.getStanzaFilter()); 098 } 099 100 public static NoResponseException newWith(XMPPConnection connection, StanzaFilter filter) { 101 final StringBuilder sb = getWaitingFor(connection); 102 sb.append(" Waited for response using: "); 103 if (filter != null) { 104 sb.append(filter.toString()); 105 } 106 else { 107 sb.append("No filter used or filter was 'null'"); 108 } 109 sb.append('.'); 110 return new NoResponseException(sb.toString(), filter); 111 } 112 113 private static StringBuilder getWaitingFor(XMPPConnection connection) { 114 final long replyTimeout = connection.getReplyTimeout(); 115 final StringBuilder sb = new StringBuilder(256); 116 sb.append("No response received within reply timeout. Timeout was " 117 + replyTimeout + "ms (~" 118 + replyTimeout / 1000 + "s)."); 119 return sb; 120 } 121 } 122 123 public static class NotLoggedInException extends SmackException { 124 125 /** 126 * 127 */ 128 private static final long serialVersionUID = 3216216839100019278L; 129 130 public NotLoggedInException() { 131 super("Client is not logged in"); 132 } 133 } 134 135 public static class AlreadyLoggedInException extends SmackException { 136 137 /** 138 * 139 */ 140 private static final long serialVersionUID = 5011416918049935231L; 141 142 public AlreadyLoggedInException() { 143 super("Client is already logged in"); 144 } 145 } 146 147 public static class AlreadyConnectedException extends SmackException { 148 149 /** 150 * 151 */ 152 private static final long serialVersionUID = 5011416918049135231L; 153 154 public AlreadyConnectedException() { 155 super("Client is already connected"); 156 } 157 } 158 159 public static class NotConnectedException extends SmackException { 160 161 /** 162 * 163 */ 164 private static final long serialVersionUID = 9197980400776001173L; 165 166 public NotConnectedException() { 167 this(null); 168 } 169 170 public NotConnectedException(String optionalHint) { 171 super("Client is not, or no longer, connected." 172 + (optionalHint != null ? ' ' + optionalHint : "")); 173 } 174 175 public NotConnectedException(XMPPConnection connection, String details) { 176 super("The connection " + connection.toString() + " is no longer connected. " 177 + details); 178 } 179 180 public NotConnectedException(XMPPConnection connection, StanzaFilter stanzaFilter) { 181 super("The connection " + connection 182 + " is no longer connected while waiting for response with " + stanzaFilter); 183 } 184 } 185 186 public static class IllegalStateChangeException extends SmackException { 187 188 /** 189 * 190 */ 191 private static final long serialVersionUID = -1766023961577168927L; 192 193 public IllegalStateChangeException() { 194 } 195 } 196 197 public static abstract class SecurityRequiredException extends SmackException { 198 199 /** 200 * 201 */ 202 private static final long serialVersionUID = 384291845029773545L; 203 204 public SecurityRequiredException(String message) { 205 super(message); 206 } 207 } 208 209 public static class SecurityRequiredByClientException extends SecurityRequiredException { 210 /** 211 * 212 */ 213 private static final long serialVersionUID = 2395325821201543159L; 214 215 public SecurityRequiredByClientException() { 216 super("SSL/TLS required by client but not supported by server"); 217 } 218 } 219 220 public static class SecurityRequiredByServerException extends SecurityRequiredException { 221 /** 222 * 223 */ 224 private static final long serialVersionUID = 8268148813117631819L; 225 226 public SecurityRequiredByServerException() { 227 super("SSL/TLS required by server but disabled in client"); 228 } 229 } 230 231 public static class SecurityNotPossibleException extends SmackException { 232 233 /** 234 * 235 */ 236 private static final long serialVersionUID = -6836090872690331336L; 237 238 public SecurityNotPossibleException(String message) { 239 super(message); 240 } 241 } 242 243 /** 244 * ConnectionException is thrown if Smack is unable to connect to all hosts of a given XMPP 245 * service. The failed hosts can be retrieved with 246 * {@link ConnectionException#getFailedAddresses()}, which will have the exception causing the 247 * connection failure set and retrievable with {@link HostAddress#getExceptions()}. 248 */ 249 public static class ConnectionException extends SmackException { 250 251 /** 252 * 253 */ 254 private static final long serialVersionUID = 1686944201672697996L; 255 256 private final List<HostAddress> failedAddresses; 257 258 public ConnectionException(Throwable wrappedThrowable) { 259 super(wrappedThrowable); 260 failedAddresses = new ArrayList<HostAddress>(0); 261 } 262 263 private ConnectionException(String message, List<HostAddress> failedAddresses) { 264 super(message); 265 this.failedAddresses = failedAddresses; 266 } 267 268 public static ConnectionException from(List<HostAddress> failedAddresses) { 269 final String DELIMITER = ", "; 270 StringBuilder sb = new StringBuilder("The following addresses failed: "); 271 for (HostAddress hostAddress : failedAddresses) { 272 sb.append(hostAddress.getErrorMessage()); 273 sb.append(DELIMITER); 274 } 275 // Remove the last delimiter 276 sb.setLength(sb.length() - DELIMITER.length()); 277 return new ConnectionException(sb.toString(), failedAddresses); 278 } 279 280 public List<HostAddress> getFailedAddresses() { 281 return failedAddresses; 282 } 283 } 284 285 public static class FeatureNotSupportedException extends SmackException { 286 287 /** 288 * 289 */ 290 private static final long serialVersionUID = 4713404802621452016L; 291 292 private final String feature; 293 private final Jid jid; 294 295 public FeatureNotSupportedException(String feature) { 296 this(feature, null); 297 } 298 299 public FeatureNotSupportedException(String feature, Jid jid) { 300 super(feature + " not supported" + (jid == null ? "" : " by '" + jid + "'")); 301 this.jid = jid; 302 this.feature = feature; 303 } 304 305 /** 306 * Get the feature which is not supported. 307 * 308 * @return the feature which is not supported 309 */ 310 public String getFeature() { 311 return feature; 312 } 313 314 /** 315 * Get JID which does not support the feature. The JID can be null in cases when there are 316 * multiple JIDs queried for this feature. 317 * 318 * @return the JID which does not support the feature, or null 319 */ 320 public Jid getJid() { 321 return jid; 322 } 323 } 324 325 public static class ResourceBindingNotOfferedException extends SmackException { 326 327 /** 328 * 329 */ 330 private static final long serialVersionUID = 2346934138253437571L; 331 332 public ResourceBindingNotOfferedException() { 333 super("Resource binding was not offered by server"); 334 } 335 } 336}