Package rocks.xmpp.extensions.last

Source Code of rocks.xmpp.extensions.last.LastActivityManager$DefaultLastActivityStrategy

/*
* The MIT License (MIT)
*
* Copyright (c) 2014 Christian Schudt
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package rocks.xmpp.extensions.last;

import rocks.xmpp.core.Jid;
import rocks.xmpp.core.XmppException;
import rocks.xmpp.core.session.ExtensionManager;
import rocks.xmpp.core.session.SessionStatusEvent;
import rocks.xmpp.core.session.SessionStatusListener;
import rocks.xmpp.core.session.XmppSession;
import rocks.xmpp.core.stanza.*;
import rocks.xmpp.core.stanza.model.AbstractPresence;
import rocks.xmpp.core.stanza.model.client.IQ;
import rocks.xmpp.extensions.last.model.LastActivity;

import java.util.Date;

/**
* The implementation of <a href="http://xmpp.org/extensions/xep-0012.html">XEP-0012: Last Activity</a> and <a href="http://xmpp.org/extensions/xep-0256.html">XEP-0256: Last Activity in Presence</a>.
* <blockquote>
* <p><cite><a href="http://xmpp.org/extensions/xep-0012.html#intro">1. Introduction</a></cite></p>
* <p>It is often helpful to know the time of the last activity associated with a entity. The canonical usage is to discover when a disconnected user last accessed its server. The 'jabber:iq:last' namespace provides a method for retrieving that information. The 'jabber:iq:last' namespace can also be used to discover or publicize when a connected user was last active on the server (i.e., the user's idle time) or to query servers and components about their current uptime.</p>
* </blockquote>
* This class also takes care about the following use case, by automatically appending last activity information to 'away' and 'xa' presences:
* <blockquote>
* <p><cite><a href="http://xmpp.org/extensions/xep-0256.html#away">1.2 Away and Extended Away</a></cite></p>
* <p>When a client automatically sets the user's {@code <show/>} value to "away" or "xa" (extended away), it can indicate when that particular was last active during the current presence session.</p>
* </blockquote>
* <p>
* By default last activity for the connected resource is updated whenever a message or available non-away, non-xa presence is sent.
* This strategy of determining last activity can be changed by {@linkplain #setLastActivityStrategy(LastActivityStrategy) setting another strategy}, e.g. a strategy which determines
* last activity by idle mouse activity.
* </p>
* <p>
* Automatic inclusion of last activity information in presence stanzas and support for this protocol can be {@linkplain #setEnabled(boolean)} enabled or disabled}.
* </p>
* <h3>Code sample</h3>
* <pre>
* <code>
* LastActivityManager lastActivityManager = xmppSession.getExtensionManager(LastActivityManager.class);
* LastActivity lastActivity = lastActivityManager.getLastActivity(Jid.valueOf("juliet@example.com/balcony"));
* </code>
* </pre>
*
* @author Christian Schudt
*/
public final class LastActivityManager extends ExtensionManager {

    private volatile LastActivityStrategy lastActivityStrategy;

    private LastActivityManager(final XmppSession xmppSession) {
        super(xmppSession, LastActivity.NAMESPACE);
        lastActivityStrategy = new DefaultLastActivityStrategy(xmppSession);

        xmppSession.addSessionStatusListener(new SessionStatusListener() {
            @Override
            public void sessionStatusChanged(SessionStatusEvent e) {
                if (e.getStatus() == XmppSession.Status.CLOSED) {
                    lastActivityStrategy = null;
                }
            }
        });
        xmppSession.addPresenceListener(new PresenceListener() {
            @Override
            public void handle(PresenceEvent e) {
                if (!e.isIncoming() && isEnabled()) {
                    AbstractPresence presence = e.getPresence();
                    if (presence.getTo() == null) {
                        synchronized (LastActivityManager.this) {
                            // If an available presence with <show/> value 'away' or 'xa' is sent, append last activity information.
                            if (lastActivityStrategy != null && lastActivityStrategy.getLastActivity() != null && presence.isAvailable() && (presence.getShow() == AbstractPresence.Show.AWAY || presence.getShow() == AbstractPresence.Show.XA) && presence.getExtension(LastActivity.class) == null) {
                                presence.getExtensions().add(new LastActivity(getSecondsSince(lastActivityStrategy.getLastActivity()), presence.getStatus()));
                            }
                        }
                    }
                }
            }
        });

        xmppSession.addIQListener(new IQListener() {
            @Override
            public void handle(IQEvent e) {
                IQ iq = e.getIQ();
                if (e.isIncoming() && isEnabled() && !e.isConsumed() && iq.getType() == IQ.Type.GET && iq.getExtension(LastActivity.class) != null) {
                    // If someone asks me to get my last activity, reply.
                    synchronized (LastActivityManager.this) {
                        IQ result = iq.createResult();
                        long seconds = (lastActivityStrategy != null && lastActivityStrategy.getLastActivity() != null) ? getSecondsSince(lastActivityStrategy.getLastActivity()) : 0;
                        result.setExtension(new LastActivity(seconds, null));
                        xmppSession.send(result);
                        e.consume();
                    }
                }
            }
        });
        setEnabled(true);
    }

    private long getSecondsSince(Date date) {
        return Math.max(0, System.currentTimeMillis() - date.getTime()) / 1000;
    }

    /**
     * Gets the last activity of the specified user.
     * <blockquote>
     * <p><cite><a href="http://xmpp.org/extensions/xep-0012.html#impl">7. Implementation Notes</a></cite></p>
     * <p>The information contained in an IQ reply for this namespace is inherently ambiguous. Specifically, for a bare JID {@code <localpart@domain.tld>} the information is the time since the JID was last connected to its server; for a full JID {@code <localpart@domain.tld/resource>} the information is the time since the resource was last active in the context of an existing session; and for a bare domain the information is the uptime for the server or component. An application MUST take these differences into account when presenting the information to a human user (if any).</p>
     * </blockquote>
     *
     * @param jid The JID for which the last activity is requested.
     * @return The last activity of the requested JID or null if the feature is not implemented or a time out has occurred.
     * @throws rocks.xmpp.core.stanza.model.StanzaException If the entity returned a stanza error.
     * @throws rocks.xmpp.core.session.NoResponseException  If the entity did not respond.
     */
    public LastActivity getLastActivity(Jid jid) throws XmppException {
        IQ result = xmppSession.query(new IQ(jid, IQ.Type.GET, new LastActivity()));
        return result.getExtension(LastActivity.class);
    }

    /**
     * Gets the currently used strategy to determine last activity of a client.
     *
     * @return The strategy.
     * @see #setLastActivityStrategy(LastActivityStrategy)
     */
    public synchronized LastActivityStrategy getLastActivityStrategy() {
        return this.lastActivityStrategy;
    }

    /**
     * Sets a strategy, which is used to determine last activity of a client.
     *
     * @param lastActivityStrategy The strategy.
     * @see #getLastActivityStrategy()
     */
    public synchronized void setLastActivityStrategy(LastActivityStrategy lastActivityStrategy) {
        this.lastActivityStrategy = lastActivityStrategy;
    }

    /**
     * The default strategy to determine last activity. It simply sets the date of last activity, whenever a message or presence is sent.
     */
    private static class DefaultLastActivityStrategy implements LastActivityStrategy {
        private volatile Date lastActivity;

        public DefaultLastActivityStrategy(XmppSession xmppSession) {
            xmppSession.addMessageListener(new MessageListener() {
                @Override
                public void handle(MessageEvent e) {
                    if (!e.isIncoming()) {
                        lastActivity = new Date();
                    }
                }
            });
            xmppSession.addPresenceListener(new PresenceListener() {
                @Override
                public void handle(PresenceEvent e) {
                    AbstractPresence presence = e.getPresence();
                    if (!e.isIncoming() && (!presence.isAvailable() || presence.getShow() != AbstractPresence.Show.AWAY && presence.getShow() != AbstractPresence.Show.XA)) {
                        lastActivity = new Date();
                    }
                }
            });
        }

        @Override
        public Date getLastActivity() {
            return lastActivity;
        }
    }
}
TOP

Related Classes of rocks.xmpp.extensions.last.LastActivityManager$DefaultLastActivityStrategy

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.