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.Map;
import java.util.WeakHashMap; 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.SmackException.NotConnectedException;
import org.jivesoftware.smack.ConnectionCreationListener;
import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.Manager; import org.jivesoftware.smack.Manager;
import org.jivesoftware.smack.PacketListener; 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.AndFilter;
import org.jivesoftware.smack.filter.IQTypeFilter; import org.jivesoftware.smack.filter.IQTypeFilter;
import org.jivesoftware.smack.filter.PacketFilter; 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 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) { private VersionManager(final XMPPConnection connection) {
super(connection); super(connection);
@ -67,13 +92,10 @@ public class VersionManager extends Manager {
* @throws NotConnectedException * @throws NotConnectedException
*/ */
public void processPacket(Packet packet) throws NotConnectedException { public void processPacket(Packet packet) throws NotConnectedException {
if (own_version == null) if (ourVersion == null)
return; return;
Version reply = new Version(own_version); connection().sendPacket(Version.createResultFor(packet, ourVersion));
reply.setPacketID(packet.getPacketID());
reply.setTo(packet.getFrom());
connection().sendPacket(reply);
} }
} }
, PACKET_FILTER); , PACKET_FILTER);
@ -90,7 +112,49 @@ public class VersionManager extends Manager {
return versionManager; return versionManager;
} }
public void setVersion(Version v) { public static void setAutoAppendSmackVersion(boolean autoAppendSmackVersion) {
own_version = v; 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.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 * 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 class Version extends IQ {
public static final String NAMESPACE = "jabber:iq:version"; public static final String NAMESPACE = "jabber:iq:version";
private String name; private final String name;
private String version; private final String version;
private String os; 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. * 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. * @param os The operating system of the queried entity. This element is OPTIONAL.
*/ */
public Version(String name, String version, String os) { 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.setType(IQ.Type.result);
this.name = name; this.name = name;
this.version = version; this.version = version;
@ -82,16 +110,6 @@ public class Version extends IQ {
return name; 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 * Returns the specific version of the software. This property will always be
* present in a result. * present in a result.
@ -102,16 +120,6 @@ public class Version extends IQ {
return version; 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 * Returns the operating system of the queried entity. This property will always be
* present in a result. * present in a result.
@ -132,21 +140,23 @@ public class Version extends IQ {
this.os = os; this.os = os;
} }
public String getChildElementXML() { @Override
StringBuilder buf = new StringBuilder(); public XmlStringBuilder getChildElementXML() {
buf.append("<query xmlns=\""); XmlStringBuilder xml = new XmlStringBuilder();
buf.append(Version.NAMESPACE); xml.halfOpenElement(IQ.QUERY_ELEMENT).xmlnsAttribute(NAMESPACE).rightAngelBracket();
buf.append("\">"); // Although not really optional elements, 'name' and 'version' are not set when sending a
if (name != null) { // version request. So we must handle the case that those are 'null' here.
buf.append("<name>").append(StringUtils.escapeForXML(name)).append("</name>"); xml.optElement("name", name);
} xml.optElement("version", version);
if (version != null) { xml.optElement("os", os);
buf.append("<version>").append(StringUtils.escapeForXML(version)).append("</version>"); xml.closeElement(IQ.QUERY_ELEMENT);
} return xml;
if (os != null) { }
buf.append("<os>").append(StringUtils.escapeForXML(os)).append("</os>");
} public static Version createResultFor(Packet request, Version version) {
buf.append("</query>"); Version result = new Version(version);
return buf.toString(); 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 class VersionProvider implements IQProvider {
public IQ parseIQ(XmlPullParser parser) throws Exception { 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; String name = null, version = null, os = null;
boolean done = false; outerloop: while (true) {
while (!done) {
int eventType = parser.next(); int eventType = parser.next();
String tagName = parser.getName(); switch (eventType) {
if (eventType == XmlPullParser.START_TAG) { case XmlPullParser.START_TAG:
if (tagName.equals("name")) { String tagName = parser.getName();
switch (tagName) {
case "name":
name = parser.nextText(); name = parser.nextText();
} break;
else if (tagName.equals("version")) { case "version":
version = parser.nextText(); version = parser.nextText();
} break;
else if (tagName.equals("os")) { case "os":
os = parser.nextText(); 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); return new Version(name, version, os);
} }
} }

View File

@ -37,7 +37,8 @@ public class VersionTest {
DummyConnection con = new DummyConnection(); DummyConnection con = new DummyConnection();
// Enable version replys for this connection // 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); IQ versionRequest = (IQ) PacketParserUtils.parseStanza(control);
assertTrue(versionRequest instanceof Version); assertTrue(versionRequest instanceof Version);