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.sm;
018
019import java.util.ArrayList;
020import java.util.Collections;
021import java.util.List;
022import java.util.concurrent.BlockingQueue;
023
024import org.jivesoftware.smack.SmackException;
025import org.jivesoftware.smack.packet.Element;
026import org.jivesoftware.smack.packet.Stanza;
027
028public abstract class StreamManagementException extends SmackException {
029
030    public StreamManagementException() {
031    }
032
033    public StreamManagementException(String message) {
034        super(message);
035    }
036
037    /**
038     *
039     */
040    private static final long serialVersionUID = 3767590115788821101L;
041
042    public static class StreamManagementNotEnabledException extends StreamManagementException {
043
044        /**
045         *
046         */
047        private static final long serialVersionUID = 2624821584352571307L;
048
049    }
050
051    public static class StreamIdDoesNotMatchException extends StreamManagementException {
052
053        /**
054         *
055         */
056        private static final long serialVersionUID = 1191073341336559621L;
057
058        public StreamIdDoesNotMatchException(String expected, String got) {
059            super("Stream IDs do not match. Expected '" + expected + "', but got '" + got + "'");
060        }
061    }
062
063    public static class StreamManagementCounterError extends StreamManagementException {
064
065        /**
066         *
067         */
068        private static final long serialVersionUID = 1L;
069
070        private final long handledCount;
071        private final long previousServerHandledCount;
072        private final long ackedStanzaCount;
073        private final int outstandingStanzasCount;
074        private final List<Stanza> ackedStanzas;
075
076        public StreamManagementCounterError(long handledCount, long previousServerHandlerCount,
077                        long ackedStanzaCount,
078                        List<Stanza> ackedStanzas) {
079            super(
080                            "There was an error regarding the Stream Management counters. Server reported "
081                                            + handledCount
082                                            + " handled stanzas, which means that the "
083                                            + ackedStanzaCount
084                                            + " recently send stanzas by client are now acked by the server. But Smack had only "
085                                            + ackedStanzas.size()
086                                            + " to acknowledge. The stanza id of the last acked outstanding stanza is "
087                                            + (ackedStanzas.isEmpty() ? "<no acked stanzas>"
088                                                            : ackedStanzas.get(ackedStanzas.size() - 1).getStanzaId()));
089            this.handledCount = handledCount;
090            this.previousServerHandledCount = previousServerHandlerCount;
091            this.ackedStanzaCount = ackedStanzaCount;
092            this.outstandingStanzasCount = ackedStanzas.size();
093            this.ackedStanzas = Collections.unmodifiableList(ackedStanzas);
094        }
095
096        public long getHandledCount() {
097            return handledCount;
098        }
099
100        public long getPreviousServerHandledCount() {
101            return previousServerHandledCount;
102        }
103
104        public long getAckedStanzaCount() {
105            return ackedStanzaCount;
106        }
107
108        public int getOutstandingStanzasCount() {
109            return outstandingStanzasCount;
110        }
111
112        public List<Stanza> getAckedStanzas() {
113            return ackedStanzas;
114        }
115    }
116
117    public static final class UnacknowledgedQueueFullException extends StreamManagementException {
118
119        /**
120         *
121         */
122        private static final long serialVersionUID = 1L;
123
124        private final int overflowElementNum;
125        private final int droppedElements;
126        private final List<Element> elements;
127        private final List<Stanza> unacknowledgesStanzas;
128
129        private UnacknowledgedQueueFullException(String message, int overflowElementNum, int droppedElements, List<Element> elements,
130                List<Stanza> unacknowledgesStanzas) {
131            super(message);
132            this.overflowElementNum = overflowElementNum;
133            this.droppedElements = droppedElements;
134            this.elements = elements;
135            this.unacknowledgesStanzas = unacknowledgesStanzas;
136        }
137
138        public int getOverflowElementNum() {
139            return overflowElementNum;
140        }
141
142        public int getDroppedElements() {
143            return droppedElements;
144        }
145
146        public List<Element> getElements() {
147            return elements;
148        }
149
150        public List<Stanza> getUnacknowledgesStanzas() {
151            return unacknowledgesStanzas;
152        }
153
154        public static UnacknowledgedQueueFullException newWith(int overflowElementNum, List<Element> elements,
155                BlockingQueue<Stanza> unacknowledgedStanzas) {
156            final int unacknowledgesStanzasQueueSize = unacknowledgedStanzas.size();
157            List<Stanza> localUnacknowledgesStanzas = new ArrayList<>(unacknowledgesStanzasQueueSize);
158            localUnacknowledgesStanzas.addAll(unacknowledgedStanzas);
159            int droppedElements = elements.size() - overflowElementNum - 1;
160
161            String message = "The queue size " + unacknowledgesStanzasQueueSize + " is not able to fit another "
162                    + droppedElements + " potential stanzas type top-level stream-elements.";
163            return new UnacknowledgedQueueFullException(message, overflowElementNum, droppedElements, elements,
164                    localUnacknowledgesStanzas);
165        }
166    }
167}
168