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