001/** 002 * 003 * Copyright 2009 Jive Software. 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.concurrent.TimeUnit; 020 021import javax.xml.namespace.QName; 022 023import org.jivesoftware.smack.SmackException.NoResponseException; 024import org.jivesoftware.smack.SmackException.NotConnectedException; 025import org.jivesoftware.smack.XMPPException.XMPPErrorException; 026import org.jivesoftware.smack.filter.IQReplyFilter; 027import org.jivesoftware.smack.filter.StanzaFilter; 028import org.jivesoftware.smack.iqrequest.IQRequestHandler; 029import org.jivesoftware.smack.packet.ExtensionElement; 030import org.jivesoftware.smack.packet.FullyQualifiedElement; 031import org.jivesoftware.smack.packet.IQ; 032import org.jivesoftware.smack.packet.Message; 033import org.jivesoftware.smack.packet.MessageBuilder; 034import org.jivesoftware.smack.packet.Nonza; 035import org.jivesoftware.smack.packet.Presence; 036import org.jivesoftware.smack.packet.PresenceBuilder; 037import org.jivesoftware.smack.packet.Stanza; 038import org.jivesoftware.smack.packet.StanzaFactory; 039import org.jivesoftware.smack.util.Consumer; 040import org.jivesoftware.smack.util.Predicate; 041import org.jivesoftware.smack.util.XmppElementUtil; 042 043import org.jxmpp.jid.DomainBareJid; 044import org.jxmpp.jid.EntityFullJid; 045 046/** 047 * The XMPPConnection interface provides an interface for connections to an XMPP server and 048 * implements shared methods which are used by the different types of connections (e.g. 049 * <code>XMPPTCPConnection</code> or <code>XMPPBOSHConnection</code>). To create a connection to an XMPP server 050 * a simple usage of this API might look like the following: 051 * 052 * <pre> 053 * // Create a connection to the igniterealtime.org XMPP server. 054 * XMPPTCPConnection con = new XMPPTCPConnection("igniterealtime.org"); 055 * // Connect to the server 056 * con.connect(); 057 * // Most servers require you to login before performing other tasks. 058 * con.login("jsmith", "mypass"); 059 * // Start a new conversation with John Doe and send him a message. 060 * ChatManager chatManager = ChatManager.getInstanceFor(con); 061 * chatManager.addIncomingListener(new IncomingChatMessageListener() { 062 * public void newIncomingMessage(EntityBareJid from, Message message, Chat chat) { 063 * // Print out any messages we get back to standard out. 064 * System.out.println("Received message: " + message); 065 * } 066 * }); 067 * Chat chat = chatManager.chatWith("jdoe@igniterealtime.org"); 068 * chat.send("Howdy!"); 069 * // Disconnect from the server 070 * con.disconnect(); 071 * </pre> 072 * <p> 073 * Note that the XMPPConnection interface does intentionally not declare any methods that manipulate 074 * the connection state, e.g. <code>connect()</code>, <code>disconnect()</code>. You should use the 075 * most specific connection type, e.g. <code>XMPPTCPConnection</code> as declared type and use the 076 * XMPPConnection interface when you don't need to manipulate the connection state. 077 * </p> 078 * <p> 079 * XMPPConnections can be reused between connections. This means that an Connection may be connected, 080 * disconnected and then connected again. Listeners of the XMPPConnection will be retained across 081 * connections. 082 * </p> 083 * <h2>Incoming Stanza Listeners</h2> 084 * Most callbacks (listeners, handlers, …) than you can add to a connection come in three different variants: 085 * <ul> 086 * <li>standard</li> 087 * <li>async (asynchronous)</li> 088 * <li>sync (synchronous)</li> 089 * </ul> 090 * <p> 091 * Standard callbacks are invoked concurrently, but it is ensured that the same callback is never run concurrently. 092 * The callback's identity is used as key for that. The events delivered to the callback preserve the order of the 093 * causing events of the connection. 094 * </p> 095 * <p> 096 * Asynchronous callbacks are run decoupled from the connections main event loop. Hence a callback triggered by 097 * stanza B may (appear to) invoked before a callback triggered by stanza A, even though stanza A arrived before B. 098 * </p> 099 * <p> 100 * Synchronous callbacks are run synchronous to the main event loop of a connection. Hence they are invoked in the 101 * exact order of how events happen there, most importantly the arrival order of incoming stanzas. You should only 102 * use synchronous callbacks in rare situations. 103 * </p> 104 * 105 * @author Matt Tucker 106 * @author Guenther Niess 107 */ 108public interface XMPPConnection { 109 110 /** 111 * Returns the XMPP Domain of the service provided by the XMPP server and used for this connection. After 112 * authenticating with the server the returned value may be different. 113 * 114 * @return the XMPP domain of this XMPP session. 115 */ 116 DomainBareJid getXMPPServiceDomain(); 117 118 /** 119 * Returns the host name of the server where the XMPP server is running. This would be the 120 * IP address of the server or a name that may be resolved by a DNS server. 121 * 122 * @return the host name of the server where the XMPP server is running or null if not yet connected. 123 */ 124 String getHost(); 125 126 /** 127 * Returns the port number of the XMPP server for this connection. The default port 128 * for normal connections is 5222. 129 * 130 * @return the port number of the XMPP server or 0 if not yet connected. 131 */ 132 int getPort(); 133 134 /** 135 * Returns the full XMPP address of the user that is logged in to the connection or 136 * <code>null</code> if not logged in yet. An XMPP address is in the form 137 * username@server/resource. 138 * 139 * @return the full XMPP address of the user logged in. 140 */ 141 EntityFullJid getUser(); 142 143 /** 144 * Returns the stream ID for this connection, which is the value set by the server 145 * when opening an XMPP stream. This value will be <code>null</code> if not connected to the server. 146 * 147 * @return the ID of this connection returned from the XMPP server or <code>null</code> if 148 * not connected to the server. 149 * @see <a href="http://xmpp.org/rfcs/rfc6120.html#streams-attr-id">RFC 6120 § 4.7.3. id</a> 150 */ 151 String getStreamId(); 152 153 /** 154 * Returns true if currently connected to the XMPP server. 155 * 156 * @return true if connected. 157 */ 158 boolean isConnected(); 159 160 /** 161 * Returns true if currently authenticated by successfully calling the login method. 162 * 163 * @return true if authenticated. 164 */ 165 boolean isAuthenticated(); 166 167 /** 168 * Returns true if currently authenticated anonymously. 169 * 170 * @return true if authenticated anonymously. 171 */ 172 boolean isAnonymous(); 173 174 /** 175 * Returns true if the connection to the server has successfully negotiated encryption. 176 * 177 * @return true if a secure connection to the server. 178 */ 179 boolean isSecureConnection(); 180 181 /** 182 * Returns true if network traffic is being compressed. When using stream compression network 183 * traffic can be reduced up to 90%. Therefore, stream compression is ideal when using a slow 184 * speed network connection. However, the server will need to use more CPU time in order to 185 * un/compress network data so under high load the server performance might be affected. 186 * 187 * @return true if network traffic is being compressed. 188 */ 189 boolean isUsingCompression(); 190 191 StanzaFactory getStanzaFactory(); 192 193 /** 194 * Sends the specified stanza to the server. 195 * 196 * @param stanza the stanza to send. 197 * @throws NotConnectedException if the connection is not connected. 198 * @throws InterruptedException if the calling thread was interrupted. 199 * */ 200 void sendStanza(Stanza stanza) throws NotConnectedException, InterruptedException; 201 202 /** 203 * Try to send the given stanza. Returns {@code true} if the stanza was successfully put into the outgoing stanza 204 * queue, otherwise, if {@code false} is returned, the stanza could not be scheduled for sending (for example 205 * because the outgoing element queue is full). Note that this means that the stanza possibly was not put onto the 206 * wire, even if {@code true} is returned, it just has been successfully scheduled for sending. 207 * <p> 208 * <b>Note:</b> Implementations are not required to provide that functionality. In that case this method is mapped 209 * to {@link #sendStanza(Stanza)} and will possibly block until the stanza could be scheduled for sending. 210 * </p> 211 * 212 * @param stanza the stanza to send. 213 * @return {@code true} if the stanza was successfully scheduled to be send, {@code false} otherwise. 214 * @throws NotConnectedException if the connection is not connected. 215 * @since 4.4.0 216 */ 217 boolean trySendStanza(Stanza stanza) throws NotConnectedException; 218 219 /** 220 * Try to send the given stanza. Returns {@code true} if the stanza was successfully put into the outgoing stanza 221 * queue within the given timeout period, otherwise, if {@code false} is returned, the stanza could not be scheduled 222 * for sending (for example because the outgoing element queue is full). Note that this means that the stanza 223 * possibly was not put onto the wire, even if {@code true} is returned, it just has been successfully scheduled for 224 * sending. 225 * <p> 226 * <b>Note:</b> Implementations are not required to provide that functionality. In that case this method is mapped 227 * to {@link #sendStanza(Stanza)} and will possibly block until the stanza could be scheduled for sending. 228 * </p> 229 * 230 * @param stanza the stanza to send. 231 * @param timeout how long to wait before giving up, in units of {@code unit}. 232 * @param unit a {@code TimeUnit} determining how to interpret the {@code timeout} parameter. 233 * @return {@code true} if the stanza was successfully scheduled to be send, {@code false} otherwise. 234 * @throws NotConnectedException if the connection is not connected. 235 * @throws InterruptedException if the calling thread was interrupted. 236 * @since 4.4.0 237 */ 238 boolean trySendStanza(Stanza stanza, long timeout, TimeUnit unit) throws NotConnectedException, InterruptedException; 239 240 /** 241 * Send a Nonza. 242 * <p> 243 * <b>This method is not meant for end-user usage!</b> It allows sending plain stream elements, which should not be 244 * done by a user manually. <b>Doing so may result in a unstable or unusable connection.</b> Certain Smack APIs use 245 * this method to send plain stream elements. 246 * </p> 247 * 248 * @param nonza the Nonza to send. 249 * @throws NotConnectedException if the XMPP connection is not connected. 250 * @throws InterruptedException if the calling thread was interrupted. 251 */ 252 void sendNonza(Nonza nonza) throws NotConnectedException, InterruptedException; 253 254 /** 255 * Adds a connection listener to this connection that will be notified when 256 * the connection closes or fails. 257 * 258 * @param connectionListener a connection listener. 259 */ 260 void addConnectionListener(ConnectionListener connectionListener); 261 262 /** 263 * Removes a connection listener from this connection. 264 * 265 * @param connectionListener a connection listener. 266 */ 267 void removeConnectionListener(ConnectionListener connectionListener); 268 269 /** 270 * Send an IQ request and wait for the response. 271 * 272 * @param request the IQ request 273 * @param <I> the type of the expected result IQ. 274 * @return an IQ with type 'result' 275 * @throws NoResponseException if there was no response from the remote entity. 276 * @throws XMPPErrorException if there was an XMPP error returned. 277 * @throws NotConnectedException if the XMPP connection is not connected. 278 * @throws InterruptedException if the calling thread was interrupted. 279 * @since 4.3 280 */ 281 <I extends IQ> I sendIqRequestAndWaitForResponse(IQ request) 282 throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException; 283 284 /** 285 * Creates a new stanza collector collecting IQ responses that are replies to the IQ <code>request</code>. 286 * Does also send the <code>request</code> IQ. The stanza filter for the collector is an 287 * {@link IQReplyFilter}, guaranteeing that stanza id and JID in the 'from' address have 288 * expected values. 289 * 290 * @param request the IQ request to filter responses from 291 * @return a new stanza collector. 292 * @throws NotConnectedException if the XMPP connection is not connected. 293 * @throws InterruptedException if the calling thread was interrupted. 294 */ 295 StanzaCollector createStanzaCollectorAndSend(IQ request) throws NotConnectedException, InterruptedException; 296 297 /** 298 * Creates a new stanza collector for this connection. A stanza filter determines 299 * which stanzas will be accumulated by the collector. A StanzaCollector is 300 * more suitable to use than a {@link StanzaListener} when you need to wait for 301 * a specific result. 302 * 303 * @param stanzaFilter the stanza filter to use. 304 * @param stanza the stanza to send right after the collector got created 305 * @return a new stanza collector. 306 * @throws InterruptedException if the calling thread was interrupted. 307 * @throws NotConnectedException if the XMPP connection is not connected. 308 */ 309 StanzaCollector createStanzaCollectorAndSend(StanzaFilter stanzaFilter, Stanza stanza) 310 throws NotConnectedException, InterruptedException; 311 312 /** 313 * Creates a new stanza collector for this connection. A stanza filter 314 * determines which stanzas will be accumulated by the collector. A 315 * StanzaCollector is more suitable to use than a {@link StanzaListener} 316 * when you need to wait for a specific result. 317 * <p> 318 * <b>Note:</b> If you send a Stanza right after using this method, then 319 * consider using 320 * {@link #createStanzaCollectorAndSend(StanzaFilter, Stanza)} instead. 321 * Otherwise make sure cancel the StanzaCollector in every case, e.g. even 322 * if an exception is thrown, or otherwise you may leak the StanzaCollector. 323 * </p> 324 * 325 * @param stanzaFilter the stanza filter to use. 326 * @return a new stanza collector. 327 */ 328 StanzaCollector createStanzaCollector(StanzaFilter stanzaFilter); 329 330 /** 331 * Create a new stanza collector with the given stanza collector configuration. 332 * <p> 333 * Please make sure to cancel the collector when it is no longer required. See also 334 * {@link #createStanzaCollector(StanzaFilter)}. 335 * </p> 336 * 337 * @param configuration the stanza collector configuration. 338 * @return a new stanza collector. 339 * @since 4.1 340 */ 341 StanzaCollector createStanzaCollector(StanzaCollector.Configuration configuration); 342 343 /** 344 * Remove a stanza collector of this connection. 345 * 346 * @param collector a stanza collectors which was created for this connection. 347 */ 348 void removeStanzaCollector(StanzaCollector collector); 349 350 /** 351 * Registers a stanza listener with this connection. The listener will be invoked when a (matching) incoming stanza 352 * is received. The stanza filter determines which stanzas will be delivered to the listener. It is guaranteed that 353 * the same listener will not be invoked concurrently and the the order of invocation will reflect the order in 354 * which the stanzas have been received. If the same stanza listener is added again with a different filter, only 355 * the new filter will be used. 356 * 357 * @param stanzaListener the stanza listener to notify of new received stanzas. 358 * @param stanzaFilter the stanza filter to use. 359 * @since 4.4.0 360 */ 361 void addStanzaListener(StanzaListener stanzaListener, StanzaFilter stanzaFilter); 362 363 /** 364 * Removes a stanza listener for received stanzas from this connection. 365 * 366 * @param stanzaListener the stanza listener to remove. 367 * @return true if the stanza listener was removed. 368 * @since 4.4.0 369 */ 370 boolean removeStanzaListener(StanzaListener stanzaListener); 371 372 /** 373 * Registers a <b>synchronous</b> stanza listener with this connection. A stanza listener will be invoked only when 374 * an incoming stanza is received. A stanza filter determines which stanzas will be delivered to the listener. If 375 * the same stanza listener is added again with a different filter, only the new filter will be used. 376 * <p> 377 * <b>Important:</b> This stanza listeners will be called in the same <i>single</i> thread that processes all 378 * incoming stanzas. Only use this kind of stanza filter if it does not perform any XMPP activity that waits for a 379 * response. Consider using {@link #addAsyncStanzaListener(StanzaListener, StanzaFilter)} when possible, i.e. when 380 * the invocation order doesn't have to be the same as the order of the arriving stanzas. If the order of the 381 * arriving stanzas, consider using a {@link StanzaCollector} when possible. 382 * </p> 383 * 384 * @param stanzaListener the stanza listener to notify of new received stanzas. 385 * @param stanzaFilter the stanza filter to use. 386 * @see #addStanzaInterceptor(StanzaListener, StanzaFilter) 387 * @since 4.1 388 */ 389 void addSyncStanzaListener(StanzaListener stanzaListener, StanzaFilter stanzaFilter); 390 391 /** 392 * Removes a stanza listener for received stanzas from this connection. 393 * 394 * @param stanzaListener the stanza listener to remove. 395 * @return true if the stanza listener was removed 396 * @since 4.1 397 */ 398 boolean removeSyncStanzaListener(StanzaListener stanzaListener); 399 400 /** 401 * Registers an <b>asynchronous</b> stanza listener with this connection. A stanza listener will be invoked only 402 * when an incoming stanza is received. A stanza filter determines which stanzas will be delivered to the listener. 403 * If the same stanza listener is added again with a different filter, only the new filter will be used. 404 * <p> 405 * Unlike {@link #addAsyncStanzaListener(StanzaListener, StanzaFilter)} stanza listeners added with this method will be 406 * invoked asynchronously in their own thread. Use this method if the order of the stanza listeners must not depend 407 * on the order how the stanzas where received. 408 * </p> 409 * 410 * @param stanzaListener the stanza listener to notify of new received stanzas. 411 * @param stanzaFilter the stanza filter to use. 412 * @see #addStanzaInterceptor(StanzaListener, StanzaFilter) 413 * @since 4.1 414 */ 415 void addAsyncStanzaListener(StanzaListener stanzaListener, StanzaFilter stanzaFilter); 416 417 /** 418 * Removes an <b>asynchronous</b> stanza listener for received stanzas from this connection. 419 * 420 * @param stanzaListener the stanza listener to remove. 421 * @return true if the stanza listener was removed 422 * @since 4.1 423 */ 424 boolean removeAsyncStanzaListener(StanzaListener stanzaListener); 425 426 /** 427 * Registers a stanza listener with this connection. The listener will be 428 * notified of every stanza that this connection sends. A stanza filter determines 429 * which stanzas will be delivered to the listener. Note that the thread 430 * that writes stanzas will be used to invoke the listeners. Therefore, each 431 * stanza listener should complete all operations quickly or use a different 432 * thread for processing. 433 * 434 * @param stanzaListener the stanza listener to notify of sent stanzas. 435 * @param stanzaFilter the stanza filter to use. 436 */ 437 void addStanzaSendingListener(StanzaListener stanzaListener, StanzaFilter stanzaFilter); 438 439 /** 440 * Removes a stanza listener for sending stanzas from this connection. 441 * 442 * @param stanzaListener the stanza listener to remove. 443 */ 444 void removeStanzaSendingListener(StanzaListener stanzaListener); 445 446 /** 447 * Registers a stanza interceptor with this connection. The interceptor will be 448 * invoked every time a stanza is about to be sent by this connection. Interceptors 449 * may modify the stanza to be sent. A stanza filter determines which stanzas 450 * will be delivered to the interceptor. 451 * 452 * <p> 453 * NOTE: For a similar functionality on incoming stanzas, see {@link #addAsyncStanzaListener(StanzaListener, StanzaFilter)}. 454 * </p> 455 * 456 * @param stanzaInterceptor the stanza interceptor to notify of stanzas about to be sent. 457 * @param stanzaFilter the stanza filter to use. 458 * @deprecated use {@link #addMessageInterceptor(Consumer, Predicate)} or {@link #addPresenceInterceptor(Consumer, Predicate)} instead. 459 */ 460 @Deprecated 461 // TODO: Remove in Smack 4.5. 462 void addStanzaInterceptor(StanzaListener stanzaInterceptor, StanzaFilter stanzaFilter); 463 464 /** 465 * Removes a stanza interceptor. 466 * 467 * @param stanzaInterceptor the stanza interceptor to remove. 468 * @deprecated use {@link #removeMessageInterceptor(Consumer)} or {@link #removePresenceInterceptor(Consumer)} instead. 469 */ 470 @Deprecated 471 // TODO: Remove in Smack 4.5. 472 void removeStanzaInterceptor(StanzaListener stanzaInterceptor); 473 474 /** 475 * Registers a stanza interceptor with this connection. The interceptor will be 476 * invoked every time a stanza is about to be sent by this connection. Interceptors 477 * may modify the stanza to be sent. A stanza filter determines which stanzas 478 * will be delivered to the interceptor. 479 * 480 * <p> 481 * NOTE: For a similar functionality on incoming stanzas, see {@link #addAsyncStanzaListener(StanzaListener, StanzaFilter)}. 482 * </p> 483 * 484 * @param messageInterceptor the stanza interceptor to notify of stanzas about to be sent. 485 * @param messageFilter the stanza filter to use. 486 */ 487 void addMessageInterceptor(Consumer<MessageBuilder> messageInterceptor, Predicate<Message> messageFilter); 488 489 /** 490 * Removes a message interceptor. 491 * 492 * @param messageInterceptor the message interceptor to remove. 493 */ 494 void removeMessageInterceptor(Consumer<MessageBuilder> messageInterceptor); 495 496 /** 497 * Registers a stanza interceptor with this connection. The interceptor will be 498 * invoked every time a stanza is about to be sent by this connection. Interceptors 499 * may modify the stanza to be sent. A stanza filter determines which stanzas 500 * will be delivered to the interceptor. 501 * 502 * <p> 503 * NOTE: For a similar functionality on incoming stanzas, see {@link #addAsyncStanzaListener(StanzaListener, StanzaFilter)}. 504 * </p> 505 * 506 * @param presenceInterceptor the stanza interceptor to notify of stanzas about to be sent. 507 * @param presenceFilter the stanza filter to use. 508 */ 509 void addPresenceInterceptor(Consumer<PresenceBuilder> presenceInterceptor, Predicate<Presence> presenceFilter); 510 511 /** 512 * Removes a presence interceptor. 513 * 514 * @param presenceInterceptor the stanza interceptor to remove. 515 */ 516 void removePresenceInterceptor(Consumer<PresenceBuilder> presenceInterceptor); 517 /** 518 * Returns the current value of the reply timeout in milliseconds for request for this 519 * XMPPConnection instance. 520 * 521 * @return the reply timeout in milliseconds 522 */ 523 long getReplyTimeout(); 524 525 /** 526 * Set the stanza reply timeout in milliseconds. In most cases, Smack will throw a 527 * {@link NoResponseException} if no reply to a request was received within the timeout period. 528 * 529 * @param timeout for a reply in milliseconds 530 */ 531 void setReplyTimeout(long timeout); 532 533 /** 534 * Get the connection counter of this XMPPConnection instance. Those can be used as ID to 535 * identify the connection, but beware that the ID may not be unique if you create more then 536 * <code>2*Integer.MAX_VALUE</code> instances as the counter could wrap. 537 * 538 * @return the connection counter of this XMPPConnection 539 */ 540 int getConnectionCounter(); 541 542 enum FromMode { 543 /** 544 * Leave the 'from' attribute unchanged. This is the behavior of Smack < 4.0 545 */ 546 UNCHANGED, 547 /** 548 * Omit the 'from' attribute. According to RFC 6120 8.1.2.1 1. XMPP servers "MUST (...) 549 * override the 'from' attribute specified by the client". It is therefore safe to specify 550 * FromMode.OMITTED here. 551 */ 552 OMITTED, 553 /** 554 * Set the from to the clients full JID. This is usually not required. 555 */ 556 USER 557 } 558 559 /** 560 * Set the FromMode for this connection instance. Defines how the 'from' attribute of outgoing 561 * stanzas should be populated by Smack. 562 * 563 * @param fromMode TODO javadoc me please 564 */ 565 void setFromMode(FromMode fromMode); 566 567 /** 568 * Get the currently active FromMode. 569 * 570 * @return the currently active {@link FromMode} 571 */ 572 FromMode getFromMode(); 573 574 /** 575 * Get the feature stanza extensions for a given stream feature of the 576 * server, or <code>null</code> if the server doesn't support that feature. 577 * 578 * @param <F> {@link ExtensionElement} type of the feature. 579 * @param element TODO javadoc me please 580 * @param namespace TODO javadoc me please 581 * @return a stanza extensions of the feature or <code>null</code> 582 * @deprecated use {@link #getFeature(Class)} instead. 583 */ 584 // TODO: Remove in Smack 4.5. 585 @Deprecated 586 default <F extends FullyQualifiedElement> F getFeature(String element, String namespace) { 587 QName qname = new QName(namespace, element); 588 return getFeature(qname); 589 } 590 591 /** 592 * Get the feature stanza extensions for a given stream feature of the 593 * server, or <code>null</code> if the server doesn't support that feature. 594 * 595 * @param <F> {@link ExtensionElement} type of the feature. 596 * @param qname the qualified name of the XML element of feature. 597 * @return a stanza extensions of the feature or <code>null</code> 598 * @since 4.4 599 */ 600 <F extends FullyQualifiedElement> F getFeature(QName qname); 601 602 /** 603 * Get the feature stanza extensions for a given stream feature of the 604 * server, or <code>null</code> if the server doesn't support that feature. 605 * 606 * @param <F> {@link ExtensionElement} type of the feature. 607 * @param featureClass the class of the feature. 608 * @return a stanza extensions of the feature or <code>null</code> 609 * @since 4.4 610 */ 611 default <F extends FullyQualifiedElement> F getFeature(Class<F> featureClass) { 612 QName qname = XmppElementUtil.getQNameFor(featureClass); 613 return getFeature(qname); 614 } 615 616 /** 617 * Return true if the server supports the given stream feature. 618 * 619 * @param element TODO javadoc me please 620 * @param namespace TODO javadoc me please 621 * @return true if the server supports the stream feature. 622 */ 623 default boolean hasFeature(String element, String namespace) { 624 QName qname = new QName(namespace, element); 625 return hasFeature(qname); 626 } 627 628 /** 629 * Return true if the server supports the given stream feature. 630 * 631 * @param qname the qualified name of the XML element of feature. 632 * @return true if the server supports the stream feature. 633 */ 634 boolean hasFeature(QName qname); 635 636 /** 637 * Send an IQ request asynchronously. The connection's default reply timeout will be used. 638 * 639 * @param request the IQ request to send. 640 * @return a SmackFuture for the response. 641 */ 642 SmackFuture<IQ, Exception> sendIqRequestAsync(IQ request); 643 644 /** 645 * Send an IQ request asynchronously. 646 * 647 * @param request the IQ request to send. 648 * @param timeout the reply timeout in milliseconds. 649 * @return a SmackFuture for the response. 650 */ 651 SmackFuture<IQ, Exception> sendIqRequestAsync(IQ request, long timeout); 652 653 /** 654 * Send a stanza asynchronously, waiting for exactly one response stanza using the given reply filter. The 655 * connection's default reply timeout will be used. 656 * 657 * @param stanza the stanza to send. 658 * @param replyFilter the filter used for the response stanza. 659 * @param <S> the type of the stanza to send. 660 * @return a SmackFuture for the response. 661 */ 662 <S extends Stanza> SmackFuture<S, Exception> sendAsync(S stanza, StanzaFilter replyFilter); 663 664 /** 665 * Send a stanza asynchronously, waiting for exactly one response stanza using the given reply filter. 666 * 667 * @param stanza the stanza to send. 668 * @param replyFilter the filter used for the response stanza. 669 * @param timeout the reply timeout in milliseconds. 670 * @param <S> the type of the stanza to send. 671 * @return a SmackFuture for the response. 672 */ 673 <S extends Stanza> SmackFuture<S, Exception> sendAsync(S stanza, StanzaFilter replyFilter, long timeout); 674 675 /** 676 * Add a callback that is called exactly once and synchronously with the incoming stanza that matches the given 677 * stanza filter. 678 * 679 * @param callback the callback invoked once the stanza filter matches a stanza. 680 * @param stanzaFilter the filter to match stanzas or null to match all. 681 */ 682 void addOneTimeSyncCallback(StanzaListener callback, StanzaFilter stanzaFilter); 683 684 /** 685 * Register an IQ request handler with this connection. 686 * <p> 687 * IQ request handler process incoming IQ requests, i.e. incoming IQ stanzas of type 'get' or 'set', and return a result. 688 * </p> 689 * @param iqRequestHandler the IQ request handler to register. 690 * @return the previously registered IQ request handler or null. 691 */ 692 IQRequestHandler registerIQRequestHandler(IQRequestHandler iqRequestHandler); 693 694 /** 695 * Convenience method for {@link #unregisterIQRequestHandler(String, String, org.jivesoftware.smack.packet.IQ.Type)}. 696 * 697 * @param iqRequestHandler TODO javadoc me please 698 * @return the previously registered IQ request handler or null. 699 */ 700 IQRequestHandler unregisterIQRequestHandler(IQRequestHandler iqRequestHandler); 701 702 /** 703 * Unregister an IQ request handler with this connection. 704 * 705 * @param element the IQ element the IQ request handler is responsible for. 706 * @param namespace the IQ namespace the IQ request handler is responsible for. 707 * @param type the IQ type the IQ request handler is responsible for. 708 * @return the previously registered IQ request handler or null. 709 */ 710 IQRequestHandler unregisterIQRequestHandler(String element, String namespace, IQ.Type type); 711 712 /** 713 * Returns the timestamp in milliseconds when the last stanza was received. 714 * 715 * @return the timestamp in milliseconds 716 */ 717 long getLastStanzaReceived(); 718}