1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-06-16 16:44:48 +02:00
Smack/smack-extensions/src/main/java/org/jivesoftware/smackx/iqversion/VersionManager.java
Florian Schmaus 717090d272 Rework incoming packet listeners and Roster
Differentiate between asynchronous and synchronous ones. Asynchronous
are the ones where the invocation order may not be the same as the order
in which the stanzas arrived.

Since it's no longer guaranteed that when a unit test calls

processPacket(stanza)

the stanza will be completely processed when the call returns, it was
necessary to extend the unit tests (mostly Roster and ChatManager) with
a packet listener that waits for his invocation. Since we now also use
LinkedHashMaps as Map for the packet listeners (SMACK-531, SMACK-424),
adding a packet listeners as last also means that it will be called as
last. We exploit this behavior change now in the unit tests.

Rename 'recvListeners' to 'syncRecvListeners' in AbstractXMPPConnection.

Rename 'rosterInitialized' to 'loaded' in Roster.

Add Roster.isLoaded().

Reset 'loaded' to false in
Roster.setOfflinePresencesAndResetLoaded() (was setOfflinePresences()).

Fixes SMACK-583, SMACK-532, SMACK-424
2015-01-07 14:35:23 +01:00

161 lines
5.6 KiB
Java

/**
*
* Copyright 2014 Georg Lukas.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.iqversion;
import java.util.Map;
import java.util.WeakHashMap;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.ConnectionCreationListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.Manager;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.XMPPConnectionRegistry;
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.filter.IQTypeFilter;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.iqversion.packet.Version;
/**
* A Version Manager that automatically responds to version IQs with a predetermined reply.
*
* <p>
* The VersionManager takes care of handling incoming version request IQs, according to
* XEP-0092 (Software Version). You can configure the version reply for a given connection
* by running the following code:
* </p>
*
* <pre>
* Version MY_VERSION = new Version("My Little XMPP Application", "v1.23", "OS/2 32-bit");
* VersionManager.getInstanceFor(mConnection).setVersion(MY_VERSION);
* </pre>
*
* @author Georg Lukas
*/
public class VersionManager extends Manager {
private static final Map<XMPPConnection, VersionManager> INSTANCES = new WeakHashMap<XMPPConnection, VersionManager>();
private static final PacketFilter PACKET_FILTER = new AndFilter(new PacketTypeFilter(Version.class), IQTypeFilter.GET);
private static Version defaultVersion;
private Version ourVersion = defaultVersion;
public static void setDefaultVersion(String name, String version) {
setDefaultVersion(name, version, null);
}
public static void setDefaultVersion(String name, String version, String os) {
defaultVersion = generateVersionFrom(name, version, os);
}
private static boolean autoAppendSmackVersion = true;
static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
public void connectionCreated(XMPPConnection connection) {
VersionManager.getInstanceFor(connection);
}
});
}
private VersionManager(final XMPPConnection connection) {
super(connection);
ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
sdm.addFeature(Version.NAMESPACE);
connection.addAsyncPacketListener(new PacketListener() {
/**
* Sends a Version reply on request
* @throws NotConnectedException
*/
public void processPacket(Packet packet) throws NotConnectedException {
if (ourVersion == null)
return;
connection().sendPacket(Version.createResultFor(packet, ourVersion));
}
}
, PACKET_FILTER);
}
public static synchronized VersionManager getInstanceFor(XMPPConnection connection) {
VersionManager versionManager = INSTANCES.get(connection);
if (versionManager == null) {
versionManager = new VersionManager(connection);
INSTANCES.put(connection, versionManager);
}
return versionManager;
}
public static void setAutoAppendSmackVersion(boolean autoAppendSmackVersion) {
VersionManager.autoAppendSmackVersion = autoAppendSmackVersion;
}
public void setVersion(String name, String version) {
setVersion(name, version, null);
}
public void setVersion(String name, String version, String os) {
ourVersion = generateVersionFrom(name, version, os);
}
public void unsetVersion() {
ourVersion = null;
}
public boolean isSupported(String jid) throws NoResponseException, XMPPErrorException,
NotConnectedException {
return ServiceDiscoveryManager.getInstanceFor(connection()).supportsFeature(jid,
Version.NAMESPACE);
}
/**
* Request version information from a given JID.
*
* @param jid
* @return the version information or {@code null} if not supported by JID
* @throws NoResponseException
* @throws XMPPErrorException
* @throws NotConnectedException
*/
public Version getVersion(String jid) throws NoResponseException, XMPPErrorException,
NotConnectedException {
if (!isSupported(jid)) {
return null;
}
return connection().createPacketCollectorAndSend(new Version(jid)).nextResultOrThrow();
}
private static Version generateVersionFrom(String name, String version, String os) {
if (autoAppendSmackVersion) {
name += " (Smack " + SmackConfiguration.getVersion() + ')';
}
return new Version(name, version, os);
}
}