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(/packet) reply timeout of the used 061 * connection instance. You can modify (e.g. increase) the stanza(/packet) 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 public static NoResponseException newWith(XMPPConnection connection, 097 StanzaCollector collector) { 098 return newWith(connection, collector.getStanzaFilter()); 099 } 100 101 public static NoResponseException newWith(XMPPConnection connection, StanzaFilter filter) { 102 final StringBuilder sb = getWaitingFor(connection); 103 sb.append(" Waited for response using: "); 104 if (filter != null) { 105 sb.append(filter.toString()); 106 } 107 else { 108 sb.append("No filter used or filter was 'null'"); 109 } 110 sb.append('.'); 111 return new NoResponseException(sb.toString(), filter); 112 } 113 114 private static StringBuilder getWaitingFor(XMPPConnection connection) { 115 final long replyTimeout = connection.getReplyTimeout(); 116 final StringBuilder sb = new StringBuilder(256); 117 sb.append("No response received within reply timeout. Timeout was " 118 + replyTimeout + "ms (~" 119 + replyTimeout / 1000 + "s)."); 120 return sb; 121 } 122 } 123 124 public static class NotLoggedInException extends SmackException { 125 126 /** 127 * 128 */ 129 private static final long serialVersionUID = 3216216839100019278L; 130 131 public NotLoggedInException() { 132 super("Client is not logged in"); 133 } 134 } 135 136 public static class AlreadyLoggedInException extends SmackException { 137 138 /** 139 * 140 */ 141 private static final long serialVersionUID = 5011416918049935231L; 142 143 public AlreadyLoggedInException() { 144 super("Client is already logged in"); 145 } 146 } 147 148 public static class AlreadyConnectedException extends SmackException { 149 150 /** 151 * 152 */ 153 private static final long serialVersionUID = 5011416918049135231L; 154 155 public AlreadyConnectedException() { 156 super("Client is already connected"); 157 } 158 } 159 160 public static class NotConnectedException extends SmackException { 161 162 /** 163 * 164 */ 165 private static final long serialVersionUID = 9197980400776001173L; 166 167 public NotConnectedException() { 168 this(null); 169 } 170 171 public NotConnectedException(String optionalHint) { 172 super("Client is not, or no longer, connected." 173 + (optionalHint != null ? ' ' + optionalHint : "")); 174 } 175 176 public NotConnectedException(XMPPConnection connection, String details) { 177 super("The connection " + connection.toString() + " is no longer connected. " 178 + details); 179 } 180 181 public NotConnectedException(XMPPConnection connection, StanzaFilter stanzaFilter) { 182 super("The connection " + connection 183 + " is no longer connected while waiting for response with " + stanzaFilter); 184 } 185 } 186 187 public static class IllegalStateChangeException extends SmackException { 188 189 /** 190 * 191 */ 192 private static final long serialVersionUID = -1766023961577168927L; 193 194 public IllegalStateChangeException() { 195 } 196 } 197 198 public static abstract class SecurityRequiredException extends SmackException { 199 200 /** 201 * 202 */ 203 private static final long serialVersionUID = 384291845029773545L; 204 205 public SecurityRequiredException(String message) { 206 super(message); 207 } 208 } 209 210 public static class SecurityRequiredByClientException extends SecurityRequiredException { 211 /** 212 * 213 */ 214 private static final long serialVersionUID = 2395325821201543159L; 215 216 public SecurityRequiredByClientException() { 217 super("SSL/TLS required by client but not supported by server"); 218 } 219 } 220 221 public static class SecurityRequiredByServerException extends SecurityRequiredException { 222 /** 223 * 224 */ 225 private static final long serialVersionUID = 8268148813117631819L; 226 227 public SecurityRequiredByServerException() { 228 super("SSL/TLS required by server but disabled in client"); 229 } 230 } 231 232 public static class SecurityNotPossibleException extends SmackException { 233 234 /** 235 * 236 */ 237 private static final long serialVersionUID = -6836090872690331336L; 238 239 public SecurityNotPossibleException(String message) { 240 super(message); 241 } 242 } 243 244 /** 245 * ConnectionException is thrown if Smack is unable to connect to all hosts of a given XMPP 246 * service. The failed hosts can be retrieved with 247 * {@link ConnectionException#getFailedAddresses()}, which will have the exception causing the 248 * connection failure set and retrievable with {@link HostAddress#getExceptions()}. 249 */ 250 public static class ConnectionException extends SmackException { 251 252 /** 253 * 254 */ 255 private static final long serialVersionUID = 1686944201672697996L; 256 257 private final List<HostAddress> failedAddresses; 258 259 public ConnectionException(Throwable wrappedThrowable) { 260 super(wrappedThrowable); 261 failedAddresses = new ArrayList<>(0); 262 } 263 264 private ConnectionException(String message, List<HostAddress> failedAddresses) { 265 super(message); 266 this.failedAddresses = failedAddresses; 267 } 268 269 public static ConnectionException from(List<HostAddress> failedAddresses) { 270 final String DELIMITER = ", "; 271 StringBuilder sb = new StringBuilder("The following addresses failed: "); 272 for (HostAddress hostAddress : failedAddresses) { 273 sb.append(hostAddress.getErrorMessage()); 274 sb.append(DELIMITER); 275 } 276 // Remove the last delimiter 277 sb.setLength(sb.length() - DELIMITER.length()); 278 return new ConnectionException(sb.toString(), failedAddresses); 279 } 280 281 public List<HostAddress> getFailedAddresses() { 282 return failedAddresses; 283 } 284 } 285 286 public static class FeatureNotSupportedException extends SmackException { 287 288 /** 289 * 290 */ 291 private static final long serialVersionUID = 4713404802621452016L; 292 293 private final String feature; 294 private final Jid jid; 295 296 public FeatureNotSupportedException(String feature) { 297 this(feature, null); 298 } 299 300 public FeatureNotSupportedException(String feature, Jid jid) { 301 super(feature + " not supported" + (jid == null ? "" : " by '" + jid + "'")); 302 this.jid = jid; 303 this.feature = feature; 304 } 305 306 /** 307 * Get the feature which is not supported. 308 * 309 * @return the feature which is not supported 310 */ 311 public String getFeature() { 312 return feature; 313 } 314 315 /** 316 * Get JID which does not support the feature. The JID can be null in cases when there are 317 * multiple JIDs queried for this feature. 318 * 319 * @return the JID which does not support the feature, or null 320 */ 321 public Jid getJid() { 322 return jid; 323 } 324 } 325 326 public static class ResourceBindingNotOfferedException extends SmackException { 327 328 /** 329 * 330 */ 331 private static final long serialVersionUID = 2346934138253437571L; 332 333 public ResourceBindingNotOfferedException() { 334 super("Resource binding was not offered by server"); 335 } 336 } 337}