Improved iqVersion code

including parsing and the version class.
This commit is contained in:
Florian Schmaus 2014-08-08 14:56:54 +02:00
parent 8274a9f25b
commit c9dd1cdc40
4 changed files with 144 additions and 59 deletions

View File

@ -20,10 +20,15 @@ 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;
@ -53,7 +58,27 @@ public class VersionManager extends Manager {
private static final PacketFilter PACKET_FILTER = new AndFilter(new PacketTypeFilter(Version.class), IQTypeFilter.GET);
private Version own_version;
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);
@ -67,13 +92,10 @@ public class VersionManager extends Manager {
* @throws NotConnectedException
*/
public void processPacket(Packet packet) throws NotConnectedException {
if (own_version == null)
if (ourVersion == null)
return;
Version reply = new Version(own_version);
reply.setPacketID(packet.getPacketID());
reply.setTo(packet.getFrom());
connection().sendPacket(reply);
connection().sendPacket(Version.createResultFor(packet, ourVersion));
}
}
, PACKET_FILTER);
@ -90,7 +112,49 @@ public class VersionManager extends Manager {
return versionManager;
}
public void setVersion(Version v) {
own_version = v;
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);
}
}

View File

@ -19,7 +19,8 @@ package org.jivesoftware.smackx.iqversion.packet;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.util.XmlStringBuilder;
/**
* A Version IQ packet, which is used by XMPP clients to discover version information
@ -50,10 +51,30 @@ import org.jivesoftware.smack.util.StringUtils;
public class Version extends IQ {
public static final String NAMESPACE = "jabber:iq:version";
private String name;
private String version;
private final String name;
private final String version;
private String os;
public Version() {
name = null;
version = null;
setType(Type.get);
}
/**
* Request version IQ
*
* @param to the jid where to request version from
*/
public Version(String to) {
this();
setTo(to);
}
public Version(String name, String version) {
this(name, version, null);
}
/**
* Creates a new Version object with given details.
*
@ -62,6 +83,13 @@ public class Version extends IQ {
* @param os The operating system of the queried entity. This element is OPTIONAL.
*/
public Version(String name, String version, String os) {
if (name == null)
{
throw new IllegalArgumentException("name must not be null");
}
if (version == null) {
throw new IllegalArgumentException("version must not be null");
}
this.setType(IQ.Type.result);
this.name = name;
this.version = version;
@ -82,16 +110,6 @@ public class Version extends IQ {
return name;
}
/**
* Sets the natural-language name of the software. This message should only be
* invoked when parsing the XML and setting the property to a Version instance.
*
* @param name the natural-language name of the software.
*/
public void setName(String name) {
this.name = name;
}
/**
* Returns the specific version of the software. This property will always be
* present in a result.
@ -102,16 +120,6 @@ public class Version extends IQ {
return version;
}
/**
* Sets the specific version of the software. This message should only be
* invoked when parsing the XML and setting the property to a Version instance.
*
* @param version the specific version of the software.
*/
public void setVersion(String version) {
this.version = version;
}
/**
* Returns the operating system of the queried entity. This property will always be
* present in a result.
@ -132,21 +140,23 @@ public class Version extends IQ {
this.os = os;
}
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<query xmlns=\"");
buf.append(Version.NAMESPACE);
buf.append("\">");
if (name != null) {
buf.append("<name>").append(StringUtils.escapeForXML(name)).append("</name>");
}
if (version != null) {
buf.append("<version>").append(StringUtils.escapeForXML(version)).append("</version>");
}
if (os != null) {
buf.append("<os>").append(StringUtils.escapeForXML(os)).append("</os>");
}
buf.append("</query>");
return buf.toString();
@Override
public XmlStringBuilder getChildElementXML() {
XmlStringBuilder xml = new XmlStringBuilder();
xml.halfOpenElement(IQ.QUERY_ELEMENT).xmlnsAttribute(NAMESPACE).rightAngelBracket();
// Although not really optional elements, 'name' and 'version' are not set when sending a
// version request. So we must handle the case that those are 'null' here.
xml.optElement("name", name);
xml.optElement("version", version);
xml.optElement("os", os);
xml.closeElement(IQ.QUERY_ELEMENT);
return xml;
}
public static Version createResultFor(Packet request, Version version) {
Version result = new Version(version);
result.setPacketID(request.getPacketID());
result.setTo(request.getFrom());
return result;
}
}

View File

@ -24,26 +24,36 @@ import org.xmlpull.v1.XmlPullParser;
public class VersionProvider implements IQProvider {
public IQ parseIQ(XmlPullParser parser) throws Exception {
assert (parser.getEventType() == XmlPullParser.START_TAG);
final int initalDepth = parser.getDepth();
String name = null, version = null, os = null;
boolean done = false;
while (!done) {
outerloop: while (true) {
int eventType = parser.next();
String tagName = parser.getName();
if (eventType == XmlPullParser.START_TAG) {
if (tagName.equals("name")) {
switch (eventType) {
case XmlPullParser.START_TAG:
String tagName = parser.getName();
switch (tagName) {
case "name":
name = parser.nextText();
}
else if (tagName.equals("version")) {
break;
case "version":
version = parser.nextText();
}
else if (tagName.equals("os")) {
break;
case "os":
os = parser.nextText();
break;
}
break;
case XmlPullParser.END_TAG:
if (parser.getDepth() == initalDepth && parser.getName().equals(IQ.QUERY_ELEMENT)) {
break outerloop;
}
} else if (eventType == XmlPullParser.END_TAG && tagName.equals("query")) {
done = true;
}
}
if (name == null && version == null && os == null) {
return new Version();
}
return new Version(name, version, os);
}
}

View File

@ -37,7 +37,8 @@ public class VersionTest {
DummyConnection con = new DummyConnection();
// Enable version replys for this connection
VersionManager.getInstanceFor(con).setVersion(new Version("Test", "0.23", "DummyOS"));
VersionManager.setAutoAppendSmackVersion(false);
VersionManager.getInstanceFor(con).setVersion("Test", "0.23", "DummyOS");
IQ versionRequest = (IQ) PacketParserUtils.parseStanza(control);
assertTrue(versionRequest instanceof Version);