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