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