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

Add support for XEP-0198: Stream Management

- De-duplicate code by moving it into AbstractXMPPConnection
- Introduce TopLevelStreamElement as superclass for all XMPP stream elements.
- Add SynchronizationPoint, ParserUtils
- Add ParserUtils

Fixes SMACK-333 and SMACK-521
This commit is contained in:
Florian Schmaus 2014-09-11 09:49:16 +02:00
parent 07c10a7444
commit fc51f3df48
69 changed files with 3277 additions and 1083 deletions

View file

@ -20,8 +20,8 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.jivesoftware.smack.packet.Element;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.NamedElement;
import org.jivesoftware.smack.util.XmlStringBuilder;
/**
@ -265,7 +265,7 @@ public class Bytestream extends IQ {
*
* @author Alexander Wenckus
*/
public static class StreamHost implements Element {
public static class StreamHost implements NamedElement {
public static String ELEMENTNAME = "streamhost";
@ -343,7 +343,7 @@ public class Bytestream extends IQ {
*
* @author Alexander Wenckus
*/
public static class StreamHostUsed implements Element {
public static class StreamHostUsed implements NamedElement {
public static String ELEMENTNAME = "streamhost-used";
@ -385,7 +385,7 @@ public class Bytestream extends IQ {
*
* @author Alexander Wenckus
*/
public static class Activate implements Element {
public static class Activate implements NamedElement {
public static String ELEMENTNAME = "activate";

View file

@ -26,6 +26,7 @@ import org.jivesoftware.smack.PacketInterceptor;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.XMPPConnectionRegistry;
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
import org.jivesoftware.smack.packet.CapsExtension;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.PacketExtension;
@ -38,7 +39,6 @@ import org.jivesoftware.smack.filter.PacketExtensionFilter;
import org.jivesoftware.smack.util.Cache;
import org.jivesoftware.smack.util.stringencoder.Base64;
import org.jivesoftware.smackx.caps.cache.EntityCapsPersistentCache;
import org.jivesoftware.smackx.caps.packet.CapsExtension;
import org.jivesoftware.smackx.disco.NodeInformationProvider;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
@ -74,8 +74,8 @@ import java.security.NoSuchAlgorithmException;
public class EntityCapsManager extends Manager {
private static final Logger LOGGER = Logger.getLogger(EntityCapsManager.class.getName());
public static final String NAMESPACE = "http://jabber.org/protocol/caps";
public static final String ELEMENT = "c";
public static final String NAMESPACE = CapsExtension.NAMESPACE;
public static final String ELEMENT = CapsExtension.ELEMENT;
private static final Map<String, MessageDigest> SUPPORTED_HASHES = new HashMap<String, MessageDigest>();
private static String DEFAULT_ENTITY_NODE = "http://www.igniterealtime.org/projects/smack";
@ -239,6 +239,17 @@ public class EntityCapsManager extends Manager {
CAPS_CACHE.clear();
}
private static void addCapsExtensionInfo(String from, CapsExtension capsExtension) {
String hash = capsExtension.getHash().toLowerCase(Locale.US);
if (!SUPPORTED_HASHES.containsKey(hash))
return;
String node = capsExtension.getNode();
String ver = capsExtension.getVer();
JID_TO_NODEVER_CACHE.put(from, new NodeVerHash(node, ver, hash));
}
private final Queue<String> lastLocalCapsVersions = new ConcurrentLinkedQueue<String>();
private final ServiceDiscoveryManager sdm;
@ -258,6 +269,20 @@ public class EntityCapsManager extends Manager {
instances.put(connection, this);
connection.addConnectionListener(new AbstractConnectionListener() {
@Override
public void connected(XMPPConnection connection) {
// It's not clear when a server would report the caps stream
// feature, so we try to process it after we are connected and
// once after we are authenticated.
processCapsStreamFeatureIfAvailable(connection);
}
@Override
public void authenticated(XMPPConnection connection) {
// It's not clear when a server would report the caps stream
// feature, so we try to process it after we are connected and
// once after we are authenticated.
processCapsStreamFeatureIfAvailable(connection);
}
@Override
public void connectionClosed() {
presenceSend = false;
@ -266,6 +291,16 @@ public class EntityCapsManager extends Manager {
public void connectionClosedOnError(Exception e) {
presenceSend = false;
}
private void processCapsStreamFeatureIfAvailable(XMPPConnection connection) {
CapsExtension capsExtension = connection.getFeature(
CapsExtension.ELEMENT, CapsExtension.NAMESPACE);
if (capsExtension == null) {
return;
}
String from = connection.getServiceName();
addCapsExtensionInfo(from, capsExtension);
}
});
// This calculates the local entity caps version
@ -282,18 +317,9 @@ public class EntityCapsManager extends Manager {
if (!entityCapsEnabled())
return;
CapsExtension ext = (CapsExtension) packet.getExtension(EntityCapsManager.ELEMENT,
EntityCapsManager.NAMESPACE);
String hash = ext.getHash().toLowerCase(Locale.US);
if (!SUPPORTED_HASHES.containsKey(hash))
return;
CapsExtension capsExtension = CapsExtension.from(packet);
String from = packet.getFrom();
String node = ext.getNode();
String ver = ext.getVer();
JID_TO_NODEVER_CACHE.put(from, new NodeVerHash(node, ver, hash));
addCapsExtensionInfo(from, capsExtension);
}
}, PRESENCES_WITH_CAPS);

View file

@ -1,66 +0,0 @@
/**
*
* Copyright © 2009 Jonas Ådahl, 2011-2014 Florian Schmaus
*
* 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.caps.packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smackx.caps.EntityCapsManager;
public class CapsExtension implements PacketExtension {
private final String node, ver, hash;
public CapsExtension(String node, String version, String hash) {
this.node = node;
this.ver = version;
this.hash = hash;
}
public String getElementName() {
return EntityCapsManager.ELEMENT;
}
public String getNamespace() {
return EntityCapsManager.NAMESPACE;
}
public String getNode() {
return node;
}
public String getVer() {
return ver;
}
public String getHash() {
return hash;
}
/*
* <c xmlns='http://jabber.org/protocol/caps'
* hash='sha-1'
* node='http://code.google.com/p/exodus'
* ver='QgayPKawpkPSDYmwT/WM94uAlu0='/>
*
*/
public CharSequence toXML() {
XmlStringBuilder xml = new XmlStringBuilder(this);
xml.attribute("hash", hash).attribute("node", node).attribute("ver", ver);
xml.closeEmptyElement();
return xml;
}
}

View file

@ -19,10 +19,10 @@ package org.jivesoftware.smackx.caps.provider;
import java.io.IOException;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.packet.CapsExtension;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.jivesoftware.smackx.caps.EntityCapsManager;
import org.jivesoftware.smackx.caps.packet.CapsExtension;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

View file

@ -28,7 +28,6 @@ import org.jxmpp.util.XmppDateTime;
*/
public class DelayInformationProvider extends AbstractDelayInformationProvider {
@SuppressWarnings("deprecation")
@Override
protected Date parseDate(String string) throws ParseException {
return XmppDateTime.parseXEP0082Date(string);

View file

@ -16,7 +16,7 @@
*/
package org.jivesoftware.smackx.muc.packet;
import org.jivesoftware.smack.packet.Element;
import org.jivesoftware.smack.packet.NamedElement;
import org.jivesoftware.smack.util.XmlStringBuilder;
/**
@ -26,7 +26,7 @@ import org.jivesoftware.smack.util.XmlStringBuilder;
*
* @author Gaston Dombiak
*/
public class Destroy implements Element {
public class Destroy implements NamedElement {
public static final String ELEMENT = "destroy";
private String reason;

View file

@ -17,7 +17,7 @@
package org.jivesoftware.smackx.muc.packet;
import org.jivesoftware.smack.packet.Element;
import org.jivesoftware.smack.packet.NamedElement;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.util.XmlStringBuilder;
@ -119,7 +119,7 @@ public class MUCInitialPresence implements PacketExtension {
*
* @author Gaston Dombiak
*/
public static class History implements Element {
public static class History implements NamedElement {
public static final String ELEMENT = "history";

View file

@ -16,8 +16,8 @@
*/
package org.jivesoftware.smackx.muc.packet;
import org.jivesoftware.smack.packet.Element;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.NamedElement;
import org.jivesoftware.smack.util.XmlStringBuilder;
import org.jivesoftware.smackx.muc.MUCAffiliation;
import org.jivesoftware.smackx.muc.MUCRole;
@ -27,7 +27,7 @@ import org.jivesoftware.smackx.muc.MUCRole;
*
* @author Gaston Dombiak
*/
public class MUCItem implements Element {
public class MUCItem implements NamedElement {
public static final String ELEMENT = IQ.ITEM;
private final MUCAffiliation affiliation;

View file

@ -17,7 +17,7 @@
package org.jivesoftware.smackx.muc.packet;
import org.jivesoftware.smack.packet.Element;
import org.jivesoftware.smack.packet.NamedElement;
import org.jivesoftware.smack.packet.Packet;
import java.util.HashMap;
@ -218,7 +218,7 @@ public class MUCUser implements PacketExtension {
*
* @author Gaston Dombiak
*/
public static class Invite implements Element {
public static class Invite implements NamedElement {
public static final String ELEMENT ="invite";
private String reason;
@ -304,7 +304,7 @@ public class MUCUser implements PacketExtension {
*
* @author Gaston Dombiak
*/
public static class Decline implements Element {
public static class Decline implements NamedElement {
public static final String ELEMENT = "decline";
private String reason;
@ -390,7 +390,7 @@ public class MUCUser implements PacketExtension {
*
* @author Gaston Dombiak
*/
public static class Status implements Element {
public static class Status implements NamedElement {
public static final String ELEMENT = "status";
private static final Map<Integer, Status> statusMap = new HashMap<Integer, Status>(8);

View file

@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
@ -27,6 +28,8 @@ import java.util.GregorianCalendar;
import java.util.Properties;
import java.util.TimeZone;
import javax.xml.parsers.FactoryConfigurationError;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jxmpp.util.XmppDateTime;
@ -35,14 +38,17 @@ import org.jivesoftware.smackx.delay.DelayInformationManager;
import org.jivesoftware.smackx.delay.packet.DelayInformation;
import org.junit.Test;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import com.jamesmurty.utils.XMLBuilder;
public class DelayInformationTest extends InitExtensions {
private static final Calendar calendar = new GregorianCalendar(2002, 9 - 1, 10, 23, 8, 25);
private static Properties outputProperties = new Properties();
static {
outputProperties.put(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes");
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
}
@Test
@ -95,8 +101,6 @@ public class DelayInformationTest extends InitExtensions {
DelayInformationProvider p = new DelayInformationProvider();
DelayInformation delayInfo;
String control;
GregorianCalendar calendar = new GregorianCalendar(2002, 9 - 1, 10, 23, 8, 25);
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
// XEP-0082 date format
control = XMLBuilder.create("delay")
@ -132,6 +136,14 @@ public class DelayInformationTest extends InitExtensions {
delayInfo = (DelayInformation) p.parseExtension(PacketParserUtils.getParserFor(control));
assertEquals(calendar.getTime(), delayInfo.getStamp());
}
@Test
public void legacyDateFormatsTest() throws FactoryConfigurationError, XmlPullParserException, IOException, Exception {
LegacyDelayInformationProvider p = new LegacyDelayInformationProvider();
DelayInformation delayInfo;
String control;
// XEP-0091 date format
control = XMLBuilder.create("x")