mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-12-26 22:27:58 +01:00
Streamline LastActivity API, add enable/disable
Allow LastActivity to be enabled/disabled. The API is now similar to the ones of the other Managers. Added unit tests.
This commit is contained in:
parent
978f692eb0
commit
010a86444a
4 changed files with 146 additions and 52 deletions
|
@ -17,7 +17,9 @@
|
|||
|
||||
package org.jivesoftware.smack.filter;
|
||||
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.packet.Packet;
|
||||
import org.jivesoftware.smack.packet.Presence;
|
||||
|
||||
/**
|
||||
* Filters for packets of a particular type. The type is given as a Class object, so
|
||||
|
@ -32,6 +34,9 @@ import org.jivesoftware.smack.packet.Packet;
|
|||
*/
|
||||
public class PacketTypeFilter implements PacketFilter {
|
||||
|
||||
public static final PacketTypeFilter PRESENCE = new PacketTypeFilter(Presence.class);
|
||||
public static final PacketTypeFilter MESSAGE = new PacketTypeFilter(Message.class);
|
||||
|
||||
Class<? extends Packet> packetType;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2003-2006 Jive Software.
|
||||
* Copyright 2003-2006 Jive Software, 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.
|
||||
|
@ -17,23 +17,25 @@
|
|||
|
||||
package org.jivesoftware.smackx.iqlast;
|
||||
|
||||
import org.jivesoftware.smack.SmackException;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import org.jivesoftware.smack.SmackException.NoResponseException;
|
||||
import org.jivesoftware.smack.SmackException.NotConnectedException;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.ConnectionCreationListener;
|
||||
import org.jivesoftware.smack.PacketListener;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smack.Manager;
|
||||
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.IQ;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.packet.Packet;
|
||||
import org.jivesoftware.smack.packet.Presence;
|
||||
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
||||
import org.jivesoftware.smackx.iqlast.packet.LastActivity;
|
||||
|
||||
/**
|
||||
|
@ -79,25 +81,46 @@ import org.jivesoftware.smackx.iqlast.packet.LastActivity;
|
|||
* </pre>
|
||||
*
|
||||
* @author Gabriel Guardincerri
|
||||
* @author Florian Schmaus
|
||||
* @see <a href="http://xmpp.org/extensions/xep-0012.html">XEP-0012: Last
|
||||
* Activity</a>
|
||||
*/
|
||||
|
||||
public class LastActivityManager {
|
||||
public class LastActivityManager extends Manager {
|
||||
private static final Map<XMPPConnection, LastActivityManager> instances = new WeakHashMap<XMPPConnection, LastActivityManager>();
|
||||
private static final PacketFilter IQ_GET_LAST_FILTER = new AndFilter(new IQTypeFilter(
|
||||
IQ.Type.GET), new PacketTypeFilter(LastActivity.class));
|
||||
|
||||
private long lastMessageSent;
|
||||
private static boolean enabledPerDefault = true;
|
||||
|
||||
private XMPPConnection connection;
|
||||
/**
|
||||
* Enable or disable Last Activity for new XMPPConnections.
|
||||
*
|
||||
* @param enabledPerDefault
|
||||
*/
|
||||
public static void setEnabledPerDefault(boolean enabledPerDefault) {
|
||||
LastActivityManager.enabledPerDefault = enabledPerDefault;
|
||||
}
|
||||
|
||||
// Enable the LastActivity support on every established connection
|
||||
static {
|
||||
XMPPConnection.addConnectionCreationListener(new ConnectionCreationListener() {
|
||||
public void connectionCreated(XMPPConnection connection) {
|
||||
new LastActivityManager(connection);
|
||||
LastActivityManager.getInstanceFor(connection);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static synchronized LastActivityManager getInstanceFor(XMPPConnection connection) {
|
||||
LastActivityManager lastActivityManager = instances.get(connection);
|
||||
if (lastActivityManager == null)
|
||||
lastActivityManager = new LastActivityManager(connection);
|
||||
return lastActivityManager;
|
||||
}
|
||||
|
||||
private long lastMessageSent;
|
||||
private boolean enabled = false;
|
||||
|
||||
/**
|
||||
* Creates a last activity manager to response last activity requests.
|
||||
*
|
||||
|
@ -105,7 +128,7 @@ public class LastActivityManager {
|
|||
* The XMPPConnection that the last activity requests will use.
|
||||
*/
|
||||
private LastActivityManager(XMPPConnection connection) {
|
||||
this.connection = connection;
|
||||
super(connection);
|
||||
|
||||
// Listen to all the sent messages to reset the idle time on each one
|
||||
connection.addPacketSendingListener(new PacketListener() {
|
||||
|
@ -123,9 +146,9 @@ public class LastActivityManager {
|
|||
break;
|
||||
}
|
||||
}
|
||||
}, new PacketTypeFilter(Presence.class));
|
||||
}, PacketTypeFilter.PRESENCE);
|
||||
|
||||
connection.addPacketListener(new PacketListener() {
|
||||
connection.addPacketSendingListener(new PacketListener() {
|
||||
@Override
|
||||
public void processPacket(Packet packet) {
|
||||
Message message = (Message) packet;
|
||||
|
@ -133,12 +156,13 @@ public class LastActivityManager {
|
|||
if (message.getType() == Message.Type.error) return;
|
||||
resetIdleTime();
|
||||
}
|
||||
}, new PacketTypeFilter(Message.class));
|
||||
}, PacketTypeFilter.MESSAGE);
|
||||
|
||||
// Register a listener for a last activity query
|
||||
connection.addPacketListener(new PacketListener() {
|
||||
|
||||
public void processPacket(Packet packet) throws NotConnectedException {
|
||||
if (!enabled) return;
|
||||
LastActivity message = new LastActivity();
|
||||
message.setType(IQ.Type.RESULT);
|
||||
message.setTo(packet.getFrom());
|
||||
|
@ -146,12 +170,26 @@ public class LastActivityManager {
|
|||
message.setPacketID(packet.getPacketID());
|
||||
message.setLastActivity(getIdleTime());
|
||||
|
||||
LastActivityManager.this.connection.sendPacket(message);
|
||||
connection().sendPacket(message);
|
||||
}
|
||||
|
||||
}, new AndFilter(new IQTypeFilter(IQ.Type.GET), new PacketTypeFilter(LastActivity.class)));
|
||||
ServiceDiscoveryManager.getInstanceFor(connection).addFeature(LastActivity.NAMESPACE);
|
||||
}, IQ_GET_LAST_FILTER);
|
||||
|
||||
if (enabledPerDefault) {
|
||||
enable();
|
||||
}
|
||||
resetIdleTime();
|
||||
instances.put(connection, this);
|
||||
}
|
||||
|
||||
public synchronized void enable() {
|
||||
ServiceDiscoveryManager.getInstanceFor(connection()).addFeature(LastActivity.NAMESPACE);
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
public synchronized void disable() {
|
||||
ServiceDiscoveryManager.getInstanceFor(connection()).removeFeature(LastActivity.NAMESPACE);
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -188,8 +226,6 @@ public class LastActivityManager {
|
|||
* Moreover, when the jid is a server or component (e.g., a JID of the form
|
||||
* 'host') the last activity is the uptime.
|
||||
*
|
||||
* @param con
|
||||
* the current XMPPConnection.
|
||||
* @param jid
|
||||
* the JID of the user.
|
||||
* @return the LastActivity packet of the jid.
|
||||
|
@ -198,31 +234,22 @@ public class LastActivityManager {
|
|||
* @throws NoResponseException if there was no response from the server.
|
||||
* @throws NotConnectedException
|
||||
*/
|
||||
public static LastActivity getLastActivity(XMPPConnection con, String jid)
|
||||
throws NoResponseException, XMPPErrorException, NotConnectedException {
|
||||
LastActivity activity = new LastActivity();
|
||||
activity.setTo(jid);
|
||||
|
||||
LastActivity response = (LastActivity) con.createPacketCollectorAndSend(activity).nextResultOrThrow();
|
||||
return response;
|
||||
public LastActivity getLastActivity(String jid) throws NoResponseException, XMPPErrorException,
|
||||
NotConnectedException {
|
||||
LastActivity activity = new LastActivity(jid);
|
||||
return (LastActivity) connection().createPacketCollectorAndSend(activity).nextResultOrThrow();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if Last Activity (XEP-0012) is supported by a given JID
|
||||
*
|
||||
* @param connection the connection to be used
|
||||
* @param jid a JID to be tested for Last Activity support
|
||||
* @return true if Last Activity is supported, otherwise false
|
||||
* @throws SmackException if there was no response from the server.
|
||||
* @throws NotConnectedException
|
||||
* @throws XMPPErrorException
|
||||
* @throws NoResponseException
|
||||
*/
|
||||
public static boolean isLastActivitySupported(XMPPConnection connection, String jid) throws SmackException {
|
||||
try {
|
||||
DiscoverInfo result =
|
||||
ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(jid);
|
||||
return result.containsFeature(LastActivity.NAMESPACE);
|
||||
}
|
||||
catch (XMPPException e) {
|
||||
return false;
|
||||
}
|
||||
public boolean isLastActivitySupported(String jid) throws NoResponseException, XMPPErrorException, NotConnectedException {
|
||||
return ServiceDiscoveryManager.getInstanceFor(connection()).supportsFeature(jid, LastActivity.NAMESPACE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2003-2007 Jive Software.
|
||||
* Copyright 2003-2007 Jive Software, 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.
|
||||
|
@ -22,6 +22,7 @@ import java.io.IOException;
|
|||
import org.jivesoftware.smack.SmackException;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smack.provider.IQProvider;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
|
@ -32,6 +33,7 @@ import org.xmlpull.v1.XmlPullParserException;
|
|||
* to get the last activity of a user.
|
||||
*
|
||||
* @author Derek DeMoro
|
||||
* @author Florian Schmaus
|
||||
*/
|
||||
public class LastActivity extends IQ {
|
||||
|
||||
|
@ -44,14 +46,23 @@ public class LastActivity extends IQ {
|
|||
setType(IQ.Type.GET);
|
||||
}
|
||||
|
||||
public String getChildElementXML() {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append("<query xmlns=\"" + NAMESPACE + "\"");
|
||||
public LastActivity(String to) {
|
||||
this();
|
||||
setTo(to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XmlStringBuilder getChildElementXML() {
|
||||
XmlStringBuilder xml = new XmlStringBuilder();
|
||||
xml.halfOpenElement("query");
|
||||
xml.xmlnsAttribute(NAMESPACE);
|
||||
if (lastActivity != -1) {
|
||||
buf.append(" seconds=\"").append(lastActivity).append("\"");
|
||||
xml.attribute("seconds", Long.toString(lastActivity));
|
||||
}
|
||||
buf.append("></query>");
|
||||
return buf.toString();
|
||||
// We don't support adding the optional message attribute, because it is usually only added
|
||||
// by XMPP servers and not by client entities.
|
||||
xml.closeEmptyElement();
|
||||
return xml;
|
||||
}
|
||||
|
||||
|
||||
|
@ -103,22 +114,17 @@ public class LastActivity extends IQ {
|
|||
|
||||
LastActivity lastActivity = new LastActivity();
|
||||
String seconds = parser.getAttributeValue("", "seconds");
|
||||
String message = null;
|
||||
try {
|
||||
message = parser.nextText();
|
||||
} catch (IOException e1) {
|
||||
// Ignore
|
||||
}
|
||||
if (seconds != null) {
|
||||
try {
|
||||
lastActivity.setLastActivity(Long.parseLong(seconds));
|
||||
} catch (NumberFormatException e) {
|
||||
// Ignore
|
||||
throw new SmackException("Could not parse last activity number", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (message != null) {
|
||||
lastActivity.setMessage(message);
|
||||
try {
|
||||
lastActivity.setMessage(parser.nextText());
|
||||
} catch (IOException e) {
|
||||
throw new SmackException(e);
|
||||
}
|
||||
return lastActivity;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 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.iqlast;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.jivesoftware.smack.DummyConnection;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smack.packet.Packet;
|
||||
import org.jivesoftware.smack.test.util.TestUtils;
|
||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||
import org.jivesoftware.smackx.InitExtensions;
|
||||
import org.jivesoftware.smackx.iqlast.packet.LastActivity;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.jamesmurty.utils.XMLBuilder;
|
||||
|
||||
public class LastActivityTest extends InitExtensions {
|
||||
|
||||
@Test
|
||||
public void checkProvider() throws Exception {
|
||||
XMLBuilder xml = XMLBuilder.create("iq");
|
||||
xml.a("from", "romeo@montague.net/orchard")
|
||||
.a("id", "last2")
|
||||
.a("to", "juliet@capulet.com/balcony")
|
||||
.a("type", "get")
|
||||
.e("query")
|
||||
.namespace(LastActivity.NAMESPACE);
|
||||
|
||||
DummyConnection c = new DummyConnection();
|
||||
IQ lastRequest = PacketParserUtils.parseIQ(TestUtils.getIQParser(xml.asString()), c);
|
||||
assertTrue(lastRequest instanceof LastActivity);
|
||||
|
||||
c.processPacket(lastRequest);;
|
||||
Packet reply = c.getSentPacket();
|
||||
assertTrue(reply instanceof LastActivity);
|
||||
LastActivity l = (LastActivity) reply;
|
||||
assertEquals("last2", l.getPacketID());
|
||||
assertEquals(IQ.Type.RESULT, l.getType());
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue