1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2025-09-09 17:19:39 +02:00

Migrate markdown documentation to javadoc

While markdown is easier to write, Smack's markdown documentation was
never tightly coupled with the source. For example, the markdown
documentation never provided links to the actual Java classes and
methods. This poses the risk that the documentation and the code
diverge over time. Furthermore, javadoc is constantly improving (for
example @snippet annotations) and I expect that one will be able to
write javadoc in markdown.

Fixes SMACK-928.
This commit is contained in:
Florian Schmaus 2023-02-03 09:36:54 +01:00
parent f65cf45b5c
commit c9a9982cef
101 changed files with 4441 additions and 5754 deletions

View file

@ -45,35 +45,34 @@ import org.jxmpp.jid.DomainBareJid;
import org.jxmpp.jid.EntityFullJid;
/**
* The XMPPConnection interface provides an interface for connections to an XMPP server and
* The XMPPConnection interface provides an interface for connections from a client to an XMPP server and
* implements shared methods which are used by the different types of connections (e.g.
* <code>XMPPTCPConnection</code> or <code>XMPPBOSHConnection</code>). To create a connection to an XMPP server
* {@link org.jivesoftware.smack.c2s.ModularXmppClientToServerConnection} or <code>XMPPTCPConnection</code>). To create a connection to an XMPP server
* a simple usage of this API might look like the following:
*
* <pre>
* // Create a connection to the igniterealtime.org XMPP server.
* XMPPTCPConnection con = new XMPPTCPConnection("igniterealtime.org");
* // Connect to the server
* con.connect();
* // Most servers require you to login before performing other tasks.
* con.login("jsmith", "mypass");
* // Start a new conversation with John Doe and send him a message.
* ChatManager chatManager = ChatManager.getInstanceFor(con);
* chatManager.addIncomingListener(new IncomingChatMessageListener() {
* public void newIncomingMessage(EntityBareJid from, Message message, Chat chat) {
* // Print out any messages we get back to standard out.
* System.out.println("Received message: " + message);
* }
* });
* Chat chat = chatManager.chatWith("jdoe@igniterealtime.org");
* chat.send("Howdy!");
* // Disconnect from the server
* con.disconnect();
* </pre>
* <pre>{@code
* // Create the configuration for this new connection
* XMPPTCPConnectionConfiguration.Builder configBuilder = XMPPTCPConnectionConfiguration.builder();
* configBuilder.setUsernameAndPassword("username", "password");
* configBuilder.setXmppDomain("jabber.org");
*
* AbstractXMPPConnection connection = new XMPPTCPConnection(configBuilder.build());
* connection.connect();
* connection.login();
*
* Message message = connection.getStanzaFactory().buildMessageStanza()
* .to("mark@example.org)
* .setBody("Hi, how are you?")
* .build();
* connection.sendStanza(message);
*
* connection.disconnect();
* }</pre>
* <p>
* Note that the XMPPConnection interface does intentionally not declare any methods that manipulate
* the connection state, e.g. <code>connect()</code>, <code>disconnect()</code>. You should use the
* most specific connection type, e.g. <code>XMPPTCPConnection</code> as declared type and use the
* most-generic superclass connection type that is able to provide the methods you require. In most cases
* this should be {@link AbstractXMPPConnection}. And use or hand out instances of the
* XMPPConnection interface when you don't need to manipulate the connection state.
* </p>
* <p>
@ -81,6 +80,13 @@ import org.jxmpp.jid.EntityFullJid;
* disconnected and then connected again. Listeners of the XMPPConnection will be retained across
* connections.
* </p>
* <h2>Processing Incoming Stanzas</h2>
* Smack provides a flexible framework for processing incoming stanzas using two constructs:
* <ul>
* <li>{@link StanzaCollector}: lets you synchronously wait for new stanzas</li>
* <li>{@link StanzaListener}: an interface for asynchronously notifying you of incoming stanzas</li>
* </ul>
*
* <h2>Incoming Stanza Listeners</h2>
* Most callbacks (listeners, handlers, ) than you can add to a connection come in three different variants:
* <ul>
@ -102,9 +108,22 @@ import org.jxmpp.jid.EntityFullJid;
* exact order of how events happen there, most importantly the arrival order of incoming stanzas. You should only
* use synchronous callbacks in rare situations.
* </p>
* <h2>Stanza Filters</h2>
* Stanza filters allow you to define the predicates for which listeners or collectors should be invoked. For more
* information about stanza filters, see {@link org.jivesoftware.smack.filter}.
* <h2>Provider Architecture</h2>
* XMPP is an extensible protocol. Smack allows for this extensible with its provider architecture that allows to
* plug-in providers that are able to parse the various XML extension elements used for XMPP's extensibility. For
* more information see {@link org.jivesoftware.smack.provider}.
* <h2>Debugging</h2>
* See {@link org.jivesoftware.smack.debugger} for Smack's API to debug XMPP connections.
* <h2>Modular Connection Architecture</h2>
* Smack's new modular connection architecture will one day replace the monolithic architecture. Its main entry
* point {@link org.jivesoftware.smack.c2s.ModularXmppClientToServerConnection} has more information.
*
* @author Matt Tucker
* @author Guenther Niess
* @author Florian Schmaus
*/
public interface XMPPConnection {

View file

@ -86,9 +86,55 @@ import org.jxmpp.jid.DomainBareJid;
import org.jxmpp.jid.parts.Resourcepart;
import org.jxmpp.util.XmppStringUtils;
/**
* The superclass of Smack's Modular Connection Architecture.
* <p>
* <b>Note:</b> Everything related to the modular connection architecture is currently considered experimental and
* should not be used in production. Use the mature {@code XMPPTCPConnection} if you do not feel adventurous.
* </p>
* <p>
* Smack's modular connection architecture allows to extend a XMPP c2s (client-to-server) connection with additional
* functionality by adding modules. Those modules extend the Finite State Machine (FSM) within the connection with new
* states. Connection modules can either be
* <ul>
* <li>Transports</li>
* <li>Extensions</li>
* </ul>
* <p>
* Transports bind the XMPP XML stream to an underlying transport like TCP, WebSockets, BOSH, and allow for the
* different particularities of transports like DirectTLS
* (<a href="https://xmpp.org/extensions/xep-0368.html">XEP-0368</a>). This eventually means that a single transport
* module can implement multiple transport mechanisms. For example the TCP transport module implements the RFC6120 TCP
* and the XEP-0368 direct TLS TCP transport bindings.
* </p>
* <p>
* Extensions allow for a richer functionality of the connection. Those include
* <ul>
* <li>Compression</li>
* <li><ul>
* <li>zlib ([XEP-0138](https://xmpp.org/extensions/xep-0138.html))</li>
* <li>[Efficient XML Interchange (EXI)](https://www.w3.org/TR/exi/)</li>
* </ul></li>
* <li>Instant Stream Resumption ([XEP-0397](https://xmpp.org/extensions/xep-0397.html)</li>
* <li>Bind2</li>
* <li>Stream Management</li>
* </ul>
* Note that not all extensions work with every transport. For example compression only works with TCP-based transport
* bindings.
* <p>
* Connection modules are plugged into the the modular connection via their constructor. and they usually declare
* backwards edges to some common, generic connection state of the FSM.
* </p>
* <p>
* Modules and states always have an accompanying *descriptor* type. `ModuleDescriptor` and `StateDescriptor` exist
* without an connection instance. They describe the module and state metadata, while their modules and states are
* Instantiated once a modular connection is instantiated.
* </p>
*/
public final class ModularXmppClientToServerConnection extends AbstractXMPPConnection {
private static final Logger LOGGER = Logger.getLogger(ModularXmppClientToServerConnectionConfiguration.class.getName());
private static final Logger LOGGER = Logger.getLogger(
ModularXmppClientToServerConnectionConfiguration.class.getName());
private final ArrayBlockingQueueWithShutdown<TopLevelStreamElement> outgoingElementsQueue = new ArrayBlockingQueueWithShutdown<>(
100, true);
@ -126,7 +172,8 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
this.configuration = configuration;
// Construct the internal connection API.
connectionInternal = new ModularXmppClientToServerConnectionInternal(this, getReactor(), debugger, outgoingElementsQueue) {
connectionInternal = new ModularXmppClientToServerConnectionInternal(this, getReactor(), debugger,
outgoingElementsQueue) {
@Override
public void parseAndProcessElement(String wrappedCompleteElement) {
@ -180,13 +227,14 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
}
@Override
public void waitForFeaturesReceived(String waitFor) throws InterruptedException, SmackException, XMPPException {
public void waitForFeaturesReceived(String waitFor)
throws InterruptedException, SmackException, XMPPException {
ModularXmppClientToServerConnection.this.waitForFeaturesReceived(waitFor);
}
@Override
public void newStreamOpenWaitForFeaturesSequence(String waitFor) throws InterruptedException,
SmackException, XMPPException {
public void newStreamOpenWaitForFeaturesSequence(String waitFor)
throws InterruptedException, SmackException, XMPPException {
ModularXmppClientToServerConnection.this.newStreamOpenWaitForFeaturesSequence(waitFor);
}
@ -196,9 +244,11 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
}
@Override
public <SN extends Nonza, FN extends Nonza> SN sendAndWaitForResponse(Nonza nonza, Class<SN> successNonzaClass,
Class<FN> failedNonzaClass) throws NoResponseException, NotConnectedException, FailedNonzaException, InterruptedException {
return ModularXmppClientToServerConnection.this.sendAndWaitForResponse(nonza, successNonzaClass, failedNonzaClass);
public <SN extends Nonza, FN extends Nonza> SN sendAndWaitForResponse(Nonza nonza,
Class<SN> successNonzaClass, Class<FN> failedNonzaClass) throws NoResponseException,
NotConnectedException, FailedNonzaException, InterruptedException {
return ModularXmppClientToServerConnection.this.sendAndWaitForResponse(nonza, successNonzaClass,
failedNonzaClass);
}
@Override
@ -234,7 +284,8 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
// modules are sometimes used to construct the states.
for (ModularXmppClientToServerConnectionModuleDescriptor moduleDescriptor : configuration.moduleDescriptors) {
Class<? extends ModularXmppClientToServerConnectionModuleDescriptor> moduleDescriptorClass = moduleDescriptor.getClass();
ModularXmppClientToServerConnectionModule<? extends ModularXmppClientToServerConnectionModuleDescriptor> connectionModule = moduleDescriptor.constructXmppConnectionModule(connectionInternal);
ModularXmppClientToServerConnectionModule<? extends ModularXmppClientToServerConnectionModuleDescriptor> connectionModule = moduleDescriptor.constructXmppConnectionModule(
connectionInternal);
connectionModules.put(moduleDescriptorClass, connectionModule);
XmppClientToServerTransport transport = connectionModule.getTransport();
@ -265,7 +316,8 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
}
private WalkStateGraphContext.Builder buildNewWalkTo(Class<? extends StateDescriptor> finalStateClass) {
return WalkStateGraphContext.builder(currentStateVertex.getElement().getStateDescriptor().getClass(), finalStateClass);
return WalkStateGraphContext.builder(currentStateVertex.getElement().getStateDescriptor().getClass(),
finalStateClass);
}
/**
@ -316,7 +368,8 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
List<GraphVertex<State>> outgoingStateEdges = initialStateVertex.getOutgoingEdges();
// See if we need to handle mandatory intermediate states.
GraphVertex<State> mandatoryIntermediateStateVertex = walkStateGraphContext.maybeReturnMandatoryImmediateState(outgoingStateEdges);
GraphVertex<State> mandatoryIntermediateStateVertex = walkStateGraphContext.maybeReturnMandatoryImmediateState(
outgoingStateEdges);
if (mandatoryIntermediateStateVertex != null) {
StateTransitionResult reason = attemptEnterState(mandatoryIntermediateStateVertex, walkStateGraphContext);
@ -340,7 +393,8 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
// state.
if (walkStateGraphContext.wouldCauseCycle(successorStateVertex)) {
// Ignore this successor.
invokeConnectionStateMachineListener(new ConnectionStateEvent.TransitionIgnoredDueCycle(initialStateVertex, successorStateVertex));
invokeConnectionStateMachineListener(new ConnectionStateEvent.TransitionIgnoredDueCycle(
initialStateVertex, successorStateVertex));
} else {
StateTransitionResult result = attemptEnterState(successorStateVertex, walkStateGraphContext);
@ -348,9 +402,11 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
break;
}
// If attemptEnterState did not throw and did not return a value of type TransitionSuccessResult, then we
// If attemptEnterState did not throw and did not return a value of type TransitionSuccessResult, then
// we
// just record this value and go on from there. Note that reason may be null, which is returned by
// attemptEnterState in case the state was already successfully handled. If this is the case, then we don't
// attemptEnterState in case the state was already successfully handled. If this is the case, then we
// don't
// record it.
if (result != null) {
walkStateGraphContext.recordFailedState(successorState, result);
@ -379,8 +435,8 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
* @throws InterruptedException if the calling thread was interrupted.
*/
private StateTransitionResult attemptEnterState(GraphVertex<State> successorStateVertex,
WalkStateGraphContext walkStateGraphContext) throws SmackException, XMPPException,
IOException, InterruptedException {
WalkStateGraphContext walkStateGraphContext)
throws SmackException, XMPPException, IOException, InterruptedException {
final GraphVertex<State> initialStateVertex = currentStateVertex;
final State initialState = initialStateVertex.getElement();
final State successorState = successorStateVertex.getElement();
@ -396,8 +452,8 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
if (successorStateDescriptor.isNotImplemented()) {
StateTransitionResult.TransitionImpossibleBecauseNotImplemented transtionImpossibleBecauseNotImplemented = new StateTransitionResult.TransitionImpossibleBecauseNotImplemented(
successorStateDescriptor);
invokeConnectionStateMachineListener(new ConnectionStateEvent.TransitionNotPossible(initialState, successorState,
transtionImpossibleBecauseNotImplemented));
invokeConnectionStateMachineListener(new ConnectionStateEvent.TransitionNotPossible(initialState,
successorState, transtionImpossibleBecauseNotImplemented));
return transtionImpossibleBecauseNotImplemented;
}
@ -406,12 +462,13 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
StateTransitionResult.TransitionImpossible transitionImpossible = successorState.isTransitionToPossible(
walkStateGraphContext);
if (transitionImpossible != null) {
invokeConnectionStateMachineListener(new ConnectionStateEvent.TransitionNotPossible(initialState, successorState,
transitionImpossible));
invokeConnectionStateMachineListener(new ConnectionStateEvent.TransitionNotPossible(initialState,
successorState, transitionImpossible));
return transitionImpossible;
}
invokeConnectionStateMachineListener(new ConnectionStateEvent.AboutToTransitionInto(initialState, successorState));
invokeConnectionStateMachineListener(
new ConnectionStateEvent.AboutToTransitionInto(initialState, successorState));
transitionAttemptResult = successorState.transitionInto(walkStateGraphContext);
} catch (SmackException | IOException | InterruptedException | XMPPException e) {
// Unwind the state here too, since this state will not be unwound by walkStateGraph(), as it will not
@ -421,8 +478,8 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
}
if (transitionAttemptResult instanceof StateTransitionResult.Failure) {
StateTransitionResult.Failure transitionFailureResult = (StateTransitionResult.Failure) transitionAttemptResult;
invokeConnectionStateMachineListener(
new ConnectionStateEvent.TransitionFailed(initialState, successorState, transitionFailureResult));
invokeConnectionStateMachineListener(new ConnectionStateEvent.TransitionFailed(initialState, successorState,
transitionFailureResult));
return transitionAttemptResult;
}
@ -566,8 +623,7 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
featuresReceived = false;
}
private void waitForFeaturesReceived(String waitFor)
throws InterruptedException, SmackException, XMPPException {
private void waitForFeaturesReceived(String waitFor) throws InterruptedException, SmackException, XMPPException {
waitForConditionOrThrowConnectionException(() -> featuresReceived, waitFor);
}
@ -577,8 +633,8 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
return streamOpenAndCloseFactory.createStreamOpen(to, from, id, lang);
}
private void newStreamOpenWaitForFeaturesSequence(String waitFor) throws InterruptedException,
SmackException, XMPPException {
private void newStreamOpenWaitForFeaturesSequence(String waitFor)
throws InterruptedException, SmackException, XMPPException {
prepareToWaitForFeaturesReceived();
// Create StreamOpen from StreamOpenAndCloseFactory via underlying transport.
@ -589,7 +645,8 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
if (localpart != null) {
from = XmppStringUtils.completeJidFrom(localpart, xmppServiceDomain);
}
AbstractStreamOpen streamOpen = streamOpenAndCloseFactory.createStreamOpen(xmppServiceDomain, from, getStreamId(), getConfiguration().getXmlLang());
AbstractStreamOpen streamOpen = streamOpenAndCloseFactory.createStreamOpen(xmppServiceDomain, from,
getStreamId(), getConfiguration().getXmlLang());
sendStreamOpen(streamOpen);
waitForFeaturesReceived(waitFor);
@ -609,7 +666,8 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
private final class DisconnectedState extends State {
private DisconnectedState(StateDescriptor stateDescriptor, ModularXmppClientToServerConnectionInternal connectionInternal) {
private DisconnectedState(StateDescriptor stateDescriptor,
ModularXmppClientToServerConnectionInternal connectionInternal) {
super(stateDescriptor, connectionInternal);
}
@ -648,7 +706,8 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
private final class LookupRemoteConnectionEndpointsState extends State {
boolean outgoingElementsQueueWasShutdown;
private LookupRemoteConnectionEndpointsState(StateDescriptor stateDescriptor, ModularXmppClientToServerConnectionInternal connectionInternal) {
private LookupRemoteConnectionEndpointsState(StateDescriptor stateDescriptor,
ModularXmppClientToServerConnectionInternal connectionInternal) {
super(stateDescriptor, connectionInternal);
}
@ -757,7 +816,8 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
}
private final class ConnectedButUnauthenticatedState extends State {
private ConnectedButUnauthenticatedState(StateDescriptor stateDescriptor, ModularXmppClientToServerConnectionInternal connectionInternal) {
private ConnectedButUnauthenticatedState(StateDescriptor stateDescriptor,
ModularXmppClientToServerConnectionInternal connectionInternal) {
super(stateDescriptor, connectionInternal);
}
@ -788,7 +848,8 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
}
private final class SaslAuthenticationState extends State {
private SaslAuthenticationState(StateDescriptor stateDescriptor, ModularXmppClientToServerConnectionInternal connectionInternal) {
private SaslAuthenticationState(StateDescriptor stateDescriptor,
ModularXmppClientToServerConnectionInternal connectionInternal) {
super(stateDescriptor, connectionInternal);
}
@ -837,14 +898,16 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
}
private final class ResourceBindingState extends State {
private ResourceBindingState(StateDescriptor stateDescriptor, ModularXmppClientToServerConnectionInternal connectionInternal) {
private ResourceBindingState(StateDescriptor stateDescriptor,
ModularXmppClientToServerConnectionInternal connectionInternal) {
super(stateDescriptor, connectionInternal);
}
@Override
public StateTransitionResult.AttemptResult transitionInto(WalkStateGraphContext walkStateGraphContext)
throws IOException, SmackException, InterruptedException, XMPPException {
// Calling bindResourceAndEstablishSession() below requires the lastFeaturesReceived sync point to be signaled.
// Calling bindResourceAndEstablishSession() below requires the lastFeaturesReceived sync point to be
// signaled.
// Since we entered this state, the FSM has decided that the last features have been received, hence signal
// the sync point.
lastFeaturesReceived = true;
@ -901,13 +964,12 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
if (walkFromDisconnectToAuthenticated != null) {
// If there was already a previous walk to ConnectedButUnauthenticated, then the context of the current
// walk must not start from the 'Disconnected' state.
assert walkStateGraphContext.getWalk().get(0).getStateDescriptor().getClass()
!= DisconnectedStateDescriptor.class;
assert walkStateGraphContext.getWalk().get(
0).getStateDescriptor().getClass() != DisconnectedStateDescriptor.class;
// Append the current walk to the previous one.
walkStateGraphContext.appendWalkTo(walkFromDisconnectToAuthenticated);
} else {
walkFromDisconnectToAuthenticated = new ArrayList<>(
walkStateGraphContext.getWalkLength() + 1);
walkFromDisconnectToAuthenticated = new ArrayList<>(walkStateGraphContext.getWalkLength() + 1);
walkStateGraphContext.appendWalkTo(walkFromDisconnectToAuthenticated);
}
walkFromDisconnectToAuthenticated.add(this);
@ -937,7 +999,8 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
}
@Override
public StateTransitionResult.TransitionImpossible isTransitionToPossible(WalkStateGraphContext walkStateGraphContext) {
public StateTransitionResult.TransitionImpossible isTransitionToPossible(
WalkStateGraphContext walkStateGraphContext) {
ensureNotOnOurWayToAuthenticatedAndResourceBound(walkStateGraphContext);
return null;
}
@ -968,7 +1031,8 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
XmppInputOutputFilter filter = it.next();
try {
filter.waitUntilInputOutputClosed();
} catch (IOException | CertificateException | InterruptedException | SmackException | XMPPException e) {
} catch (IOException | CertificateException | InterruptedException | SmackException
| XMPPException e) {
LOGGER.log(Level.WARNING, "waitUntilInputOutputClosed() threw", e);
}
}
@ -991,12 +1055,14 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
}
private static final class InstantShutdownState extends NoOpState {
private InstantShutdownState(ModularXmppClientToServerConnection connection, StateDescriptor stateDescriptor, ModularXmppClientToServerConnectionInternal connectionInternal) {
private InstantShutdownState(ModularXmppClientToServerConnection connection, StateDescriptor stateDescriptor,
ModularXmppClientToServerConnectionInternal connectionInternal) {
super(connection, stateDescriptor, connectionInternal);
}
@Override
public StateTransitionResult.TransitionImpossible isTransitionToPossible(WalkStateGraphContext walkStateGraphContext) {
public StateTransitionResult.TransitionImpossible isTransitionToPossible(
WalkStateGraphContext walkStateGraphContext) {
ensureNotOnOurWayToAuthenticatedAndResourceBound(walkStateGraphContext);
return null;
}
@ -1057,8 +1123,8 @@ public final class ModularXmppClientToServerConnection extends AbstractXMPPConne
@Override
protected void connectInternal() throws SmackException, IOException, XMPPException, InterruptedException {
WalkStateGraphContext walkStateGraphContext = buildNewWalkTo(ConnectedButUnauthenticatedStateDescriptor.class)
.build();
WalkStateGraphContext walkStateGraphContext = buildNewWalkTo(
ConnectedButUnauthenticatedStateDescriptor.class).build();
walkStateGraph(walkStateGraphContext);
}

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2015 Florian Schmaus
* Copyright 2002-2008 Jive Software, 2015-2022 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,6 +16,18 @@
*/
/**
* Core debugger functionality.
* Smack includes built-in debugging consoles that will let you track all XML traffic between the client and server.
* Further debuggers, besides those provide by smack-core, can be found in org.jivesoftware.smackx.debugger (note, that
* this uses the smackx namespace, and not smack) provided by smack-debug.
*
* Debugging mode can be enabled in two different ways.
*
* Add the following line of code before creating new connections
*
* {@code SmackConfiguration.DEBUG = true;}
*
* Set the Java system property smack.debugEnabled to {@code true}. The system property can be set on the command line such as
*
* <pre>java -Dsmack.debugEnabled=true SomeApp</pre>
*/
package org.jivesoftware.smack.debugger;

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2015 Florian Schmaus
* Copyright 2015-2022 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,5 +17,16 @@
/**
* Allows {@link org.jivesoftware.smack.StanzaCollector} and {@link org.jivesoftware.smack.StanzaListener} instances to filter for stanzas with particular attributes.
* <h2>Selected Filter Types</h2>
* <ul>
* <li>{@link StanzaTypeFilter}: filters for stanzas that are a stanza type (Message, Presence, or IQ)</li>
* <li>{@link StanzaIdFilter}: filters for stanzas with a particular stanza ID</li>
* <li>{@link ToMatchesFilter}: filters for stanzas that are sent to a particular address</li>
* <li>{@link FromMatchesFilter}: filters for stanzas that are sent from a particular address</li>
* <li>{@link ExtensionElementFilter}: filters for stanzas that have a particular stanza exentsion element</li>
* <li>{@link AndFilter}: implements the logical AND operation over two or more filters</li>
* <li>{@link OrFilter}: implements the logical OR operation over two or more filters</li>
* <li>{@link NotFilter}: implements the logical NOT operation on a filter</li>
* </ul>
*/
package org.jivesoftware.smack.filter;

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2019-2021 Florian Schmaus
* Copyright 2019-2022 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -31,6 +31,62 @@ import org.jivesoftware.smack.xml.XmlPullParserException;
* An abstract class for parsing custom {@link IQ} packets. Each IqProvider must be registered with the {@link
* ProviderManager} for it to be used. Every implementation of this abstract class <b>must</b> have a public,
* no-argument constructor.
* <h2>Custom IQ Provider Example</h2>
* <p>
* Let us assume you want to write a provider for a new, unsupported IQ in Smack.
* </p>
* <pre>{@code
* <iq type='set' from='juliet@capulet.example/balcony' to='romeo@montage.example'>
* <myiq xmlns='example:iq:foo' token='secret'>
* <user age='42'>John Doe</user>
* <location>New York</location>
* </myiq>
* </iq>
* }</pre>
* The custom IQ provider may look like the follows
* <pre>{@code
* public class MyIQProvider extends IQProvider<MyIQ> {
*
* {@literal @}Override
* public MyIQ parse(XmlPullParser parser, int initialDepth) throws XmlPullParserException, IOException {
* // Define the data we are trying to collect with sane defaults
* int age = -1;
* String user = null;
* String location = null;
*
* // Start parsing loop
* outerloop: while(true) {
* XmlPullParser.Event eventType = parser.next();
* switch(eventType) {
* case START_ELEMENT:
* String elementName = parser.getName();
* switch (elementName) {
* case "user":
* age = ParserUtils.getIntegerAttribute(parser, "age");
* user = parser.nextText();
* break;
* case "location"
* location = parser.nextText();
* break;
* }
* break;
* case END_ELEMENT:
* // Abort condition: if the are on a end tag (closing element) of the same depth
* if (parser.getDepth() == initialDepth) {
* break outerloop;
* }
* break;
* default:
* // Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
* break;
* }
* }
*
* // Construct the IQ instance at the end of parsing, when all data has been collected
* return new MyIQ(user, age, location);
* }
* }
* }</pre>
*
* @param <I> the {@link IQ} that is parsed by implementations.
*/

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2015 Florian Schmaus
* Copyright 2015-2022 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,6 +16,29 @@
*/
/**
* Provides pluggable parsing of incoming IQ's and extensions elements.
* The Smack provider architecture is a system for plugging in custom XML parsing of staza extensions
* ({@link org.jivesoftware.smack.packet.ExtensionElement}, {@link org.jivesoftware.smack.packet.IQ} stanzas and
* {@link org.jivesoftware.smack.packet.Nonza}. Hence, there are the the following providers:
* <ul>
* <li>{@link ExtensionElementProvider}</li>
* <li>{@link IqProvider}</li>
* <li>{@link NonzaProvider}</li>
* </ul>
* For most users, only extension element and IQ providers should be relevant.
* <h2>Architecture</h2>
* <p>
* Providers are registered with the {@link ProviderManager}. XML elements identified by their
* {@link javax.xml.namespace.QName}, that is, their qualified name consistent of the XML elements name and its
* namespace. The QName is hence used to map XML elements to their provider Whenever a stanza extension is found in a
* stanza, parsing will be passed to the correct provider. Each provider is responsible for parsing the XML stream via
* Smack's {@link org.jivesoftware.smack.xml.XmlPullParser}.
* </p>
* <h2>Unknown Extension Elements</h2>
* <p>
* If no extension element provider is registered for an element, then Smack will fall back to parse the "unknown"
* element to a {@link org.jivesoftware.smack.packet.StandardExtensionElement}.
* </p>
* <h2>Custom Provider Example</h2>
* See {@link IqProvider} for examples.
*/
package org.jivesoftware.smack.provider;

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2015 Florian Schmaus
* Copyright 2015-2022 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,6 +16,56 @@
*/
/**
* Utilities for DNS related tasks.
* Smack's API for DNS related tasks.
* <h2>DNSSEC and DANE</h2>
* <h3>About</h3>
* <p>
* DNSSEC (<a href="https://tools.ietf.org/html/rfc4033">RFC 4033</a>, and others) authenticates DNS answers, positive
* and negative ones. This means that if a DNS response secured by DNSSEC turns out to be authentic, then you can be
* sure that the domain either exists, and that the returned resource records (RRs) are the ones the domain owner
* authorized, or that the domain does not exists and that nobody tried to fake its non existence.
* </p>
* <p>
* The tricky part is that an application using DNSSEC can not determine whether a domain uses DNSSEC, does not use
* DNSSEC or if someone downgraded your DNS query using DNSSEC to a response without DNSSEC.
* </p>
* <p>
* DANE (<a href="https://tools.ietf.org/html/rfc6698">RFC 6698</a>) allows the verification of a TLS certificate with
* information stored in the DNS system and secured by DNSSEC. Thus DANE requires DNSSEC.
* </p>
* <h3>Prerequisites</h3>
* <p>
* From the three DNS resolver providers (MiniDNS, javax, dnsjava) supported by Smack we currently only support DNSSEc
* with <a href="https://github.com/minidns/minidns">MiniDNS</a>. MiniDNS is the default resolver when smack-android is
* used. For other configurations, make sure to add smack-resolver-minidns to your dependencies and call
* `MiniDnsResolver.setup()` prior using Smack (e.g. in a `static {}` code block).
* </p>
* <h3>DNSSEC API</h3>
* <p>
* Smack's DNSSEC API is very simple. Just use
* {@link org.jivesoftware.smack.ConnectionConfiguration.Builder#setDnssecMode(org.jivesoftware.smack.ConnectionConfiguration.DnssecMode)}
* to enable DNSSEC. The argument, {@link org.jivesoftware.smack.ConnectionConfiguration.DnssecMode}, can be one of
* <ul>
* <li>{@link org.jivesoftware.smack.ConnectionConfiguration.DnssecMode#disabled}</li>
* <li>{@link org.jivesoftware.smack.ConnectionConfiguration.DnssecMode#needsDnssec}</li>
* <li>{@link org.jivesoftware.smack.ConnectionConfiguration.DnssecMode#needsDnssecAndDane}</li>
* </ul>
* The default is disabled.
* <p>
* If {@link org.jivesoftware.smack.ConnectionConfiguration.DnssecMode#needsDnssec} is used, then then Smack will only
* connect if the DNS results required to determine a host for the XMPP domain could be verified using DNSSEC.
* </p>
* <p>
* If set to {@link org.jivesoftware.smack.ConnectionConfiguration.DnssecMode#needsDnssecAndDane}, then then DANE will
* be used to verify the XMPP service's TLS certificate if STARTTLS is used.
* </p>
* <h2>Best Practices</h2>
* <p>
* We recommend that applications using Smack's DNSSEC API do not ask the user if DNSSEC is avaialble. Instead they
* should check for DNSSEC suport on every connection attempt. Once DNSSEC support has been discovered, the application
* should use the `needsDnssec` mode for all future connection attempts. The same scheme can be applied when using DANE.
* This approach is similar to the scheme established by to <a href="https://tools.ietf.org/html/rfc6797">HTTP Strict
* Transport Security" (HSTS, RFC 6797</a>.
* </p>
*/
package org.jivesoftware.smack.util.dns;