1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $RCSfile$
3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Revision$
4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Date$
5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Copyright 2009 Jive Software.
7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * you may not use this file except in compliance with the License.
10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * You may obtain a copy of the License at
11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *     http://www.apache.org/licenses/LICENSE-2.0
13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Unless required by applicable law or agreed to in writing, software
15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * distributed under the License is distributed on an "AS IS" BASIS,
16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * See the License for the specific language governing permissions and
18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * limitations under the License.
19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.jivesoftware.smack;
22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.Reader;
24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.Writer;
25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.lang.reflect.Constructor;
26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.ArrayList;
27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Collection;
28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Collections;
29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.List;
30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Map;
31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Set;
32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.concurrent.ConcurrentHashMap;
33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.concurrent.ConcurrentLinkedQueue;
34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.concurrent.CopyOnWriteArrayList;
35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.concurrent.CopyOnWriteArraySet;
36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.concurrent.atomic.AtomicInteger;
37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.compression.JzlibInputOutputStream;
39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.compression.XMPPInputOutputStream;
40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.compression.Java7ZlibInputOutputStream;
41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.debugger.SmackDebugger;
42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.filter.PacketFilter;
43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.Packet;
44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.Presence;
45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * The abstract Connection class provides an interface for connections to a
48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * XMPP server and implements shared methods which are used by the
49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * different types of connections (e.g. XMPPConnection or BoshConnection).
50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * To create a connection to a XMPP server a simple usage of this API might
52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * look like the following:
53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <pre>
54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * // Create a connection to the igniterealtime.org XMPP server.
55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Connection con = new XMPPConnection("igniterealtime.org");
56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * // Connect to the server
57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * con.connect();
58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * // Most servers require you to login before performing other tasks.
59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * con.login("jsmith", "mypass");
60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * // Start a new conversation with John Doe and send him a message.
61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Chat chat = connection.getChatManager().createChat("jdoe@igniterealtime.org"</font>, new MessageListener() {
62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/>
63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *     public void processMessage(Chat chat, Message message) {
64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *         // Print out any messages we get back to standard out.
65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *         System.out.println(<font color="green">"Received message: "</font> + message);
66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *     }
67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * });
68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * chat.sendMessage(<font color="green">"Howdy!"</font>);
69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * // Disconnect from the server
70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * con.disconnect();
71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * </pre>
72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/>
73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Connections can be reused between connections. This means that an Connection
74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * may be connected, disconnected and then connected again. Listeners of the Connection
75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * will be retained accross connections.<p>
76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <p/>
77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * If a connected Connection gets disconnected abruptly then it will try to reconnect
78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * again. To stop the reconnection process, use {@link #disconnect()}. Once stopped
79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * you can use {@link #connect()} to manually connect to the server.
80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see XMPPConnection
82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Matt Tucker
83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Guenther Niess
84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic abstract class Connection {
86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Counter to uniquely identify connections that are created.
89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private final static AtomicInteger connectionCounter = new AtomicInteger(0);
91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * A set of listeners which will be invoked if a new connection is created.
94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private final static Set<ConnectionCreationListener> connectionEstablishedListeners =
96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            new CopyOnWriteArraySet<ConnectionCreationListener>();
97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected final static List<XMPPInputOutputStream> compressionHandlers = new ArrayList<XMPPInputOutputStream>(2);
99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Value that indicates whether debugging is enabled. When enabled, a debug
102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * window will apear for each new connection that will contain the following
103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * information:<ul>
104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * <li> Client Traffic -- raw XML traffic generated by Smack and sent to the server.
105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * <li> Server Traffic -- raw XML traffic sent by the server to the client.
106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * <li> Interpreted Packets -- shows XML packets from the server as parsed by Smack.
107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * </ul>
108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * <p/>
109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Debugging can be enabled by setting this field to true, or by setting the Java system
110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * property <tt>smack.debugEnabled</tt> to true. The system property can be set on the
111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * command line such as "java SomeApp -Dsmack.debugEnabled=true".
112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public static boolean DEBUG_ENABLED = false;
114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    static {
116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Use try block since we may not have permission to get a system
117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // property (for example, when an applet).
118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        try {
119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            DEBUG_ENABLED = Boolean.getBoolean("smack.debugEnabled");
120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        catch (Exception e) {
122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            // Ignore.
123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Ensure the SmackConfiguration class is loaded by calling a method in it.
125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        SmackConfiguration.getVersion();
126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Add the Java7 compression handler first, since it's preferred
127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        compressionHandlers.add(new Java7ZlibInputOutputStream());
128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // If we don't have access to the Java7 API use the JZlib compression handler
129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        compressionHandlers.add(new JzlibInputOutputStream());
130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * A collection of ConnectionListeners which listen for connection closing
134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * and reconnection events.
135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected final Collection<ConnectionListener> connectionListeners =
137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            new CopyOnWriteArrayList<ConnectionListener>();
138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * A collection of PacketCollectors which collects packets for a specified filter
141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * and perform blocking and polling operations on the result queue.
142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected final Collection<PacketCollector> collectors = new ConcurrentLinkedQueue<PacketCollector>();
144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * List of PacketListeners that will be notified when a new packet was received.
147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected final Map<PacketListener, ListenerWrapper> recvListeners =
149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            new ConcurrentHashMap<PacketListener, ListenerWrapper>();
150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * List of PacketListeners that will be notified when a new packet was sent.
153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected final Map<PacketListener, ListenerWrapper> sendListeners =
155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            new ConcurrentHashMap<PacketListener, ListenerWrapper>();
156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * List of PacketInterceptors that will be notified when a new packet is about to be
159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * sent to the server. These interceptors may modify the packet before it is being
160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * actually sent to the server.
161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected final Map<PacketInterceptor, InterceptorWrapper> interceptors =
163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            new ConcurrentHashMap<PacketInterceptor, InterceptorWrapper>();
164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * The AccountManager allows creation and management of accounts on an XMPP server.
167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private AccountManager accountManager = null;
169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
171d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * The ChatManager keeps track of references to all current chats.
172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected ChatManager chatManager = null;
174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
176d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * The SmackDebugger allows to log and debug XML traffic.
177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected SmackDebugger debugger = null;
179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
181d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * The Reader which is used for the {@see debugger}.
182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected Reader reader;
184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * The Writer which is used for the {@see debugger}.
187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected Writer writer;
189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * The permanent storage for the roster
192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected RosterStorage rosterStorage;
194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
195d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * The SASLAuthentication manager that is responsible for authenticating with the server.
198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected SASLAuthentication saslAuthentication = new SASLAuthentication(this);
200d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
201d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * A number to uniquely identify connections that are created. This is distinct from the
203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * connection ID, which is a value sent by the server once a connection is made.
204d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected final int connectionCounterValue = connectionCounter.getAndIncrement();
206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
207d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
208d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Holds the initial configuration used while creating the connection.
209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected final ConnectionConfiguration config;
211d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
212d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
213d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Holds the Caps Node information for the used XMPP service (i.e. the XMPP server)
214d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
215d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private String serviceCapsNode;
216d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
217d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected XMPPInputOutputStream compressionHandler;
218d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
219d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
220d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Create a new Connection to a XMPP server.
221d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
222d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param configuration The configuration which is used to establish the connection.
223d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
224d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected Connection(ConnectionConfiguration configuration) {
225d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        config = configuration;
226d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
227d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
228d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
229d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the configuration used to connect to the server.
230d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
231d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the configuration used to connect to the server.
232d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
233d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected ConnectionConfiguration getConfiguration() {
234d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return config;
235d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
236d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
237d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
238d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the name of the service provided by the XMPP server for this connection.
239d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * This is also called XMPP domain of the connected server. After
240d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * authenticating with the server the returned value may be different.
241d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
242d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the name of the service provided by the XMPP server.
243d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
244d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public String getServiceName() {
245d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return config.getServiceName();
246d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
247d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
248d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
249d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the host name of the server where the XMPP server is running. This would be the
250d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * IP address of the server or a name that may be resolved by a DNS server.
251d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
252d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the host name of the server where the XMPP server is running.
253d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
254d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public String getHost() {
255d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return config.getHost();
256d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
257d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
258d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
259d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the port number of the XMPP server for this connection. The default port
260d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * for normal connections is 5222. The default port for SSL connections is 5223.
261d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
262d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the port number of the XMPP server.
263d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
264d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public int getPort() {
265d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return config.getPort();
266d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
267d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
268d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
269d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the full XMPP address of the user that is logged in to the connection or
270d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * <tt>null</tt> if not logged in yet. An XMPP address is in the form
271d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * username@server/resource.
272d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
273d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the full XMPP address of the user logged in.
274d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
275d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public abstract String getUser();
276d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
277d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
278d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the connection ID for this connection, which is the value set by the server
279d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * when opening a XMPP stream. If the server does not set a connection ID, this value
280d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * will be null. This value will be <tt>null</tt> if not connected to the server.
281d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
282d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the ID of this connection returned from the XMPP server or <tt>null</tt> if
283d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *      not connected to the server.
284d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
285d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public abstract String getConnectionID();
286d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
287d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
288d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns true if currently connected to the XMPP server.
289d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
290d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return true if connected.
291d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
292d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public abstract boolean isConnected();
293d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
294d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
295d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns true if currently authenticated by successfully calling the login method.
296d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
297d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return true if authenticated.
298d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
299d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public abstract boolean isAuthenticated();
300d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
301d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
302d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns true if currently authenticated anonymously.
303d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
304d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return true if authenticated anonymously.
305d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
306d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public abstract boolean isAnonymous();
307d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
308d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
309d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns true if the connection to the server has successfully negotiated encryption.
310d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
311d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return true if a secure connection to the server.
312d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
313d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public abstract boolean isSecureConnection();
314d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
315d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
316d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns if the reconnection mechanism is allowed to be used. By default
317d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * reconnection is allowed.
318d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
319d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return true if the reconnection mechanism is allowed to be used.
320d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
321d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected boolean isReconnectionAllowed() {
322d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return config.isReconnectionAllowed();
323d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
324d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
325d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
326d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns true if network traffic is being compressed. When using stream compression network
327d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * traffic can be reduced up to 90%. Therefore, stream compression is ideal when using a slow
328d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * speed network connection. However, the server will need to use more CPU time in order to
329d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * un/compress network data so under high load the server performance might be affected.
330d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
331d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return true if network traffic is being compressed.
332d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
333d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public abstract boolean isUsingCompression();
334d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
335d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
336d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Establishes a connection to the XMPP server and performs an automatic login
337d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * only if the previous connection state was logged (authenticated). It basically
338d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * creates and maintains a connection to the server.<p>
339d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * <p/>
340d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Listeners will be preserved from a previous connection if the reconnection
341d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * occurs after an abrupt termination.
342d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
343d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws XMPPException if an error occurs while trying to establish the connection.
344d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
345d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public abstract void connect() throws XMPPException;
346d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
347d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
348d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Logs in to the server using the strongest authentication mode supported by
349d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * the server, then sets presence to available. If the server supports SASL authentication
350d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * then the user will be authenticated using SASL if not Non-SASL authentication will
351d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * be tried. If more than five seconds (default timeout) elapses in each step of the
352d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * authentication process without a response from the server, or if an error occurs, a
353d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * XMPPException will be thrown.<p>
354d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
355d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Before logging in (i.e. authenticate) to the server the connection must be connected.
356d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
357d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * It is possible to log in without sending an initial available presence by using
358d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * {@link ConnectionConfiguration#setSendPresence(boolean)}. If this connection is
359d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * not interested in loading its roster upon login then use
360d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * {@link ConnectionConfiguration#setRosterLoadedAtLogin(boolean)}.
361d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Finally, if you want to not pass a password and instead use a more advanced mechanism
362d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * while using SASL then you may be interested in using
363d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * {@link ConnectionConfiguration#setCallbackHandler(javax.security.auth.callback.CallbackHandler)}.
364d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * For more advanced login settings see {@link ConnectionConfiguration}.
365d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
366d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param username the username.
367d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param password the password or <tt>null</tt> if using a CallbackHandler.
368d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws XMPPException if an error occurs.
369d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
370d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void login(String username, String password) throws XMPPException {
371d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        login(username, password, "Smack");
372d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
373d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
374d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
375d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Logs in to the server using the strongest authentication mode supported by
376d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * the server, then sets presence to available. If the server supports SASL authentication
377d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * then the user will be authenticated using SASL if not Non-SASL authentication will
378d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * be tried. If more than five seconds (default timeout) elapses in each step of the
379d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * authentication process without a response from the server, or if an error occurs, a
380d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * XMPPException will be thrown.<p>
381d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
382d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Before logging in (i.e. authenticate) to the server the connection must be connected.
383d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
384d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * It is possible to log in without sending an initial available presence by using
385d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * {@link ConnectionConfiguration#setSendPresence(boolean)}. If this connection is
386d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * not interested in loading its roster upon login then use
387d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * {@link ConnectionConfiguration#setRosterLoadedAtLogin(boolean)}.
388d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Finally, if you want to not pass a password and instead use a more advanced mechanism
389d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * while using SASL then you may be interested in using
390d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * {@link ConnectionConfiguration#setCallbackHandler(javax.security.auth.callback.CallbackHandler)}.
391d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * For more advanced login settings see {@link ConnectionConfiguration}.
392d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
393d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param username the username.
394d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param password the password or <tt>null</tt> if using a CallbackHandler.
395d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param resource the resource.
396d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws XMPPException if an error occurs.
397d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws IllegalStateException if not connected to the server, or already logged in
398d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *      to the serrver.
399d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
400d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public abstract void login(String username, String password, String resource) throws XMPPException;
401d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
402d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
403d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Logs in to the server anonymously. Very few servers are configured to support anonymous
404d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * authentication, so it's fairly likely logging in anonymously will fail. If anonymous login
405d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * does succeed, your XMPP address will likely be in the form "123ABC@server/789XYZ" or
406d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * "server/123ABC" (where "123ABC" and "789XYZ" is a random value generated by the server).
407d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
408d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws XMPPException if an error occurs or anonymous logins are not supported by the server.
409d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws IllegalStateException if not connected to the server, or already logged in
410d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *      to the serrver.
411d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
412d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public abstract void loginAnonymously() throws XMPPException;
413d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
414d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
415d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Sends the specified packet to the server.
416d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
417d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param packet the packet to send.
418d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
419d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public abstract void sendPacket(Packet packet);
420d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
421d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
422d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns an account manager instance for this connection.
423d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
424d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return an account manager for this connection.
425d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
426d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public AccountManager getAccountManager() {
427d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (accountManager == null) {
428d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            accountManager = new AccountManager(this);
429d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
430d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return accountManager;
431d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
432d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
433d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
434d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns a chat manager instance for this connection. The ChatManager manages all incoming and
435d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * outgoing chats on the current connection.
436d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
437d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return a chat manager instance for this connection.
438d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
439d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public synchronized ChatManager getChatManager() {
440d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (this.chatManager == null) {
441d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            this.chatManager = new ChatManager(this);
442d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
443d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return this.chatManager;
444d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
445d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
446d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
447d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the roster for the user.
448d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * <p>
449d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * This method will never return <code>null</code>, instead if the user has not yet logged into
450d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * the server or is logged in anonymously all modifying methods of the returned roster object
451d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * like {@link Roster#createEntry(String, String, String[])},
452d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * {@link Roster#removeEntry(RosterEntry)} , etc. except adding or removing
453d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * {@link RosterListener}s will throw an IllegalStateException.
454d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
455d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the user's roster.
456d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
457d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public abstract Roster getRoster();
458d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
459d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
460d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Set the store for the roster of this connection. If you set the roster storage
461d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * of a connection you enable support for XEP-0237 (RosterVersioning)
462d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param store the store used for roster versioning
463d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws IllegalStateException if you add a roster store when roster is initializied
464d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
465d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public abstract void setRosterStorage(RosterStorage storage) throws IllegalStateException;
466d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
467d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
468d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the SASLAuthentication manager that is responsible for authenticating with
469d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * the server.
470d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
471d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the SASLAuthentication manager that is responsible for authenticating with
472d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *         the server.
473d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
474d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public SASLAuthentication getSASLAuthentication() {
475d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return saslAuthentication;
476d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
477d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
478d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
479d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Closes the connection by setting presence to unavailable then closing the connection to
480d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * the XMPP server. The Connection can still be used for connecting to the server
481d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * again.<p>
482d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * <p/>
483d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * This method cleans up all resources used by the connection. Therefore, the roster,
484d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * listeners and other stateful objects cannot be re-used by simply calling connect()
485d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * on this connection again. This is unlike the behavior during unexpected disconnects
486d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * (and subsequent connections). In that case, all state is preserved to allow for
487d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * more seamless error recovery.
488d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
489d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void disconnect() {
490d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        disconnect(new Presence(Presence.Type.unavailable));
491d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
492d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
493d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
494d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Closes the connection. A custom unavailable presence is sent to the server, followed
495d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * by closing the stream. The Connection can still be used for connecting to the server
496d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * again. A custom unavilable presence is useful for communicating offline presence
497d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * information such as "On vacation". Typically, just the status text of the presence
498d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * packet is set with online information, but most XMPP servers will deliver the full
499d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * presence packet with whatever data is set.<p>
500d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * <p/>
501d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * This method cleans up all resources used by the connection. Therefore, the roster,
502d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * listeners and other stateful objects cannot be re-used by simply calling connect()
503d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * on this connection again. This is unlike the behavior during unexpected disconnects
504d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * (and subsequent connections). In that case, all state is preserved to allow for
505d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * more seamless error recovery.
506d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
507d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param unavailablePresence the presence packet to send during shutdown.
508d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
509d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public abstract void disconnect(Presence unavailablePresence);
510d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
511d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
512d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Adds a new listener that will be notified when new Connections are created. Note
513d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * that newly created connections will not be actually connected to the server.
514d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
515d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param connectionCreationListener a listener interested on new connections.
516d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
517d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public static void addConnectionCreationListener(
518d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            ConnectionCreationListener connectionCreationListener) {
519d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        connectionEstablishedListeners.add(connectionCreationListener);
520d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
521d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
522d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
523d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Removes a listener that was interested in connection creation events.
524d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
525d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param connectionCreationListener a listener interested on new connections.
526d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
527d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public static void removeConnectionCreationListener(
528d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            ConnectionCreationListener connectionCreationListener) {
529d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        connectionEstablishedListeners.remove(connectionCreationListener);
530d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
531d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
532d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
533d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Get the collection of listeners that are interested in connection creation events.
534d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
535d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return a collection of listeners interested on new connections.
536d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
537d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected static Collection<ConnectionCreationListener> getConnectionCreationListeners() {
538d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return Collections.unmodifiableCollection(connectionEstablishedListeners);
539d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
540d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
541d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
542d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Adds a connection listener to this connection that will be notified when
543d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * the connection closes or fails. The connection needs to already be connected
544d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * or otherwise an IllegalStateException will be thrown.
545d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
546d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param connectionListener a connection listener.
547d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
548d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void addConnectionListener(ConnectionListener connectionListener) {
549d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (!isConnected()) {
550d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            throw new IllegalStateException("Not connected to server.");
551d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
552d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (connectionListener == null) {
553d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            return;
554d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
555d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (!connectionListeners.contains(connectionListener)) {
556d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            connectionListeners.add(connectionListener);
557d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
558d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
559d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
560d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
561d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Removes a connection listener from this connection.
562d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
563d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param connectionListener a connection listener.
564d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
565d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void removeConnectionListener(ConnectionListener connectionListener) {
566d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        connectionListeners.remove(connectionListener);
567d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
568d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
569d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
570d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Get the collection of listeners that are interested in connection events.
571d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
572d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return a collection of listeners interested on connection events.
573d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
574d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected Collection<ConnectionListener> getConnectionListeners() {
575d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return connectionListeners;
576d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
577d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
578d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
579d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Creates a new packet collector for this connection. A packet filter determines
580d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * which packets will be accumulated by the collector. A PacketCollector is
581d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * more suitable to use than a {@link PacketListener} when you need to wait for
582d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * a specific result.
583d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
584d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param packetFilter the packet filter to use.
585d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return a new packet collector.
586d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
587d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public PacketCollector createPacketCollector(PacketFilter packetFilter) {
588d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        PacketCollector collector = new PacketCollector(this, packetFilter);
589d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Add the collector to the list of active collectors.
590d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        collectors.add(collector);
591d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return collector;
592d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
593d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
594d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
595d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Remove a packet collector of this connection.
596d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
597d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param collector a packet collectors which was created for this connection.
598d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
599d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected void removePacketCollector(PacketCollector collector) {
600d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        collectors.remove(collector);
601d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
602d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
603d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
604d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Get the collection of all packet collectors for this connection.
605d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
606d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return a collection of packet collectors for this connection.
607d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
608d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected Collection<PacketCollector> getPacketCollectors() {
609d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return collectors;
610d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
611d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
612d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
613d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Registers a packet listener with this connection. A packet filter determines
614d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * which packets will be delivered to the listener. If the same packet listener
615d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * is added again with a different filter, only the new filter will be used.
616d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
617d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param packetListener the packet listener to notify of new received packets.
618d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param packetFilter   the packet filter to use.
619d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
620d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void addPacketListener(PacketListener packetListener, PacketFilter packetFilter) {
621d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (packetListener == null) {
622d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            throw new NullPointerException("Packet listener is null.");
623d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
624d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        ListenerWrapper wrapper = new ListenerWrapper(packetListener, packetFilter);
625d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        recvListeners.put(packetListener, wrapper);
626d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
627d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
628d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
629d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Removes a packet listener for received packets from this connection.
630d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
631d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param packetListener the packet listener to remove.
632d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
633d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void removePacketListener(PacketListener packetListener) {
634d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        recvListeners.remove(packetListener);
635d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
636d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
637d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
638d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Get a map of all packet listeners for received packets of this connection.
639d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
640d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return a map of all packet listeners for received packets.
641d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
642d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected Map<PacketListener, ListenerWrapper> getPacketListeners() {
643d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return recvListeners;
644d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
645d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
646d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
647d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Registers a packet listener with this connection. The listener will be
648d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * notified of every packet that this connection sends. A packet filter determines
649d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * which packets will be delivered to the listener. Note that the thread
650d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * that writes packets will be used to invoke the listeners. Therefore, each
651d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * packet listener should complete all operations quickly or use a different
652d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * thread for processing.
653d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
654d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param packetListener the packet listener to notify of sent packets.
655d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param packetFilter   the packet filter to use.
656d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
657d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void addPacketSendingListener(PacketListener packetListener, PacketFilter packetFilter) {
658d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (packetListener == null) {
659d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            throw new NullPointerException("Packet listener is null.");
660d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
661d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        ListenerWrapper wrapper = new ListenerWrapper(packetListener, packetFilter);
662d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        sendListeners.put(packetListener, wrapper);
663d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
664d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
665d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
666d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Removes a packet listener for sending packets from this connection.
667d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
668d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param packetListener the packet listener to remove.
669d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
670d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void removePacketSendingListener(PacketListener packetListener) {
671d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        sendListeners.remove(packetListener);
672d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
673d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
674d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
675d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Get a map of all packet listeners for sending packets of this connection.
676d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
677d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return a map of all packet listeners for sent packets.
678d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
679d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected Map<PacketListener, ListenerWrapper> getPacketSendingListeners() {
680d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return sendListeners;
681d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
682d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
683d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
684d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
685d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Process all packet listeners for sending packets.
686d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
687d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param packet the packet to process.
688d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
689d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected void firePacketSendingListeners(Packet packet) {
690d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Notify the listeners of the new sent packet
691d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        for (ListenerWrapper listenerWrapper : sendListeners.values()) {
692d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            listenerWrapper.notifyListener(packet);
693d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
694d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
695d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
696d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
697d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Registers a packet interceptor with this connection. The interceptor will be
698d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * invoked every time a packet is about to be sent by this connection. Interceptors
699d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * may modify the packet to be sent. A packet filter determines which packets
700d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * will be delivered to the interceptor.
701d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
702d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param packetInterceptor the packet interceptor to notify of packets about to be sent.
703d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param packetFilter      the packet filter to use.
704d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
705d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void addPacketInterceptor(PacketInterceptor packetInterceptor,
706d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            PacketFilter packetFilter) {
707d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (packetInterceptor == null) {
708d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            throw new NullPointerException("Packet interceptor is null.");
709d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
710d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        interceptors.put(packetInterceptor, new InterceptorWrapper(packetInterceptor, packetFilter));
711d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
712d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
713d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
714d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Removes a packet interceptor.
715d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
716d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param packetInterceptor the packet interceptor to remove.
717d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
718d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void removePacketInterceptor(PacketInterceptor packetInterceptor) {
719d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        interceptors.remove(packetInterceptor);
720d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
721d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
722d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public boolean isSendPresence() {
723d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return config.isSendPresence();
724d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
725d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
726d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
727d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Get a map of all packet interceptors for sending packets of this connection.
728d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
729d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return a map of all packet interceptors for sending packets.
730d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
731d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected Map<PacketInterceptor, InterceptorWrapper> getPacketInterceptors() {
732d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return interceptors;
733d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
734d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
735d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
736d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Process interceptors. Interceptors may modify the packet that is about to be sent.
737d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Since the thread that requested to send the packet will invoke all interceptors, it
738d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * is important that interceptors perform their work as soon as possible so that the
739d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * thread does not remain blocked for a long period.
740d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
741d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param packet the packet that is going to be sent to the server
742d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
743d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected void firePacketInterceptors(Packet packet) {
744d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (packet != null) {
745d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            for (InterceptorWrapper interceptorWrapper : interceptors.values()) {
746d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                interceptorWrapper.notifyListener(packet);
747d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
748d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
749d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
750d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
751d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
752d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Initialize the {@link #debugger}. You can specify a customized {@link SmackDebugger}
753d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * by setup the system property <code>smack.debuggerClass</code> to the implementation.
754d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
755d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws IllegalStateException if the reader or writer isn't yet initialized.
756d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws IllegalArgumentException if the SmackDebugger can't be loaded.
757d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
758d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected void initDebugger() {
759d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (reader == null || writer == null) {
760d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            throw new NullPointerException("Reader or writer isn't initialized.");
761d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
762d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // If debugging is enabled, we open a window and write out all network traffic.
763d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (config.isDebuggerEnabled()) {
764d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            if (debugger == null) {
765d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                // Detect the debugger class to use.
766d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                String className = null;
767d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                // Use try block since we may not have permission to get a system
768d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                // property (for example, when an applet).
769d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                try {
770d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    className = System.getProperty("smack.debuggerClass");
771d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                }
772d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                catch (Throwable t) {
773d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    // Ignore.
774d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                }
775d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                Class<?> debuggerClass = null;
776d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                if (className != null) {
777d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    try {
778d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                        debuggerClass = Class.forName(className);
779d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    }
780d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    catch (Exception e) {
781d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                        e.printStackTrace();
782d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    }
783d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                }
784d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                if (debuggerClass == null) {
785d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    try {
786d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                        debuggerClass =
787d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                                Class.forName("de.measite.smack.AndroidDebugger");
788d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    }
789d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    catch (Exception ex) {
790d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                        try {
791d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                            debuggerClass =
792d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                                    Class.forName("org.jivesoftware.smack.debugger.ConsoleDebugger");
793d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                        }
794d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                        catch (Exception ex2) {
795d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                            ex2.printStackTrace();
796d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                        }
797d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    }
798d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                }
799d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                // Create a new debugger instance. If an exception occurs then disable the debugging
800d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                // option
801d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                try {
802d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    Constructor<?> constructor = debuggerClass
803d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                            .getConstructor(Connection.class, Writer.class, Reader.class);
804d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    debugger = (SmackDebugger) constructor.newInstance(this, writer, reader);
805d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    reader = debugger.getReader();
806d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    writer = debugger.getWriter();
807d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                }
808d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                catch (Exception e) {
809d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    throw new IllegalArgumentException("Can't initialize the configured debugger!", e);
810d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                }
811d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
812d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            else {
813d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                // Obtain new reader and writer from the existing debugger
814d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                reader = debugger.newConnectionReader(reader);
815d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                writer = debugger.newConnectionWriter(writer);
816d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
817d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
818d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
819d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
820d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
821d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
822d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Set the servers Entity Caps node
823d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
824d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Connection holds this information in order to avoid a dependency to
825d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * smackx where EntityCapsManager lives from smack.
826d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
827d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param node
828d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
829d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected void setServiceCapsNode(String node) {
830d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        serviceCapsNode = node;
831d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
832d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
833d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
834d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Retrieve the servers Entity Caps node
835d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
836d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Connection holds this information in order to avoid a dependency to
837d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * smackx where EntityCapsManager lives from smack.
838d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
839d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return
840d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
841d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public String getServiceCapsNode() {
842d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return serviceCapsNode;
843d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
844d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
845d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
846d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * A wrapper class to associate a packet filter with a listener.
847d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
848d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected static class ListenerWrapper {
849d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
850d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        private PacketListener packetListener;
851d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        private PacketFilter packetFilter;
852d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
853d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        /**
854d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         * Create a class which associates a packet filter with a listener.
855d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         *
856d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         * @param packetListener the packet listener.
857d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         * @param packetFilter the associated filter or null if it listen for all packets.
858d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         */
859d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        public ListenerWrapper(PacketListener packetListener, PacketFilter packetFilter) {
860d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            this.packetListener = packetListener;
861d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            this.packetFilter = packetFilter;
862d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
863d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
864d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        /**
865d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         * Notify and process the packet listener if the filter matches the packet.
866d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         *
867d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         * @param packet the packet which was sent or received.
868d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         */
869d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        public void notifyListener(Packet packet) {
870d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            if (packetFilter == null || packetFilter.accept(packet)) {
871d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                packetListener.processPacket(packet);
872d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
873d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
874d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
875d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
876d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
877d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * A wrapper class to associate a packet filter with an interceptor.
878d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
879d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected static class InterceptorWrapper {
880d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
881d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        private PacketInterceptor packetInterceptor;
882d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        private PacketFilter packetFilter;
883d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
884d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        /**
885d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         * Create a class which associates a packet filter with an interceptor.
886d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         *
887d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         * @param packetInterceptor the interceptor.
888d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         * @param packetFilter the associated filter or null if it intercepts all packets.
889d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         */
890d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        public InterceptorWrapper(PacketInterceptor packetInterceptor, PacketFilter packetFilter) {
891d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            this.packetInterceptor = packetInterceptor;
892d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            this.packetFilter = packetFilter;
893d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
894d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
895d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        public boolean equals(Object object) {
896d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            if (object == null) {
897d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                return false;
898d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
899d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            if (object instanceof InterceptorWrapper) {
900d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                return ((InterceptorWrapper) object).packetInterceptor
901d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                        .equals(this.packetInterceptor);
902d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
903d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            else if (object instanceof PacketInterceptor) {
904d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                return object.equals(this.packetInterceptor);
905d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
906d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            return false;
907d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
908d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
909d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        /**
910d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         * Notify and process the packet interceptor if the filter matches the packet.
911d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         *
912d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         * @param packet the packet which will be sent.
913d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         */
914d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        public void notifyListener(Packet packet) {
915d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            if (packetFilter == null || packetFilter.accept(packet)) {
916d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                packetInterceptor.interceptPacket(packet);
917d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
918d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
919d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
920d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
921