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:
parent
07c10a7444
commit
fc51f3df48
69 changed files with 3277 additions and 1083 deletions
|
@ -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";
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue