001/**
002 *
003 * Copyright 2014 Florian Schmaus
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.jivesoftware.smackx.time;
018
019import java.util.Map;
020import java.util.WeakHashMap;
021
022import org.jivesoftware.smack.SmackException.NoResponseException;
023import org.jivesoftware.smack.SmackException.NotConnectedException;
024import org.jivesoftware.smack.XMPPConnection;
025import org.jivesoftware.smack.ConnectionCreationListener;
026import org.jivesoftware.smack.Manager;
027import org.jivesoftware.smack.PacketListener;
028import org.jivesoftware.smack.XMPPException.XMPPErrorException;
029import org.jivesoftware.smack.filter.AndFilter;
030import org.jivesoftware.smack.filter.IQTypeFilter;
031import org.jivesoftware.smack.filter.PacketFilter;
032import org.jivesoftware.smack.filter.PacketTypeFilter;
033import org.jivesoftware.smack.packet.IQ.Type;
034import org.jivesoftware.smack.packet.Packet;
035import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
036import org.jivesoftware.smackx.time.packet.Time;
037
038public class EntityTimeManager extends Manager {
039
040    private static final Map<XMPPConnection, EntityTimeManager> INSTANCES = new WeakHashMap<XMPPConnection, EntityTimeManager>();
041
042    private static final PacketFilter TIME_PACKET_FILTER = new AndFilter(new PacketTypeFilter(
043                    Time.class), new IQTypeFilter(Type.GET));
044
045    private static boolean autoEnable = true;
046
047    static {
048        XMPPConnection.addConnectionCreationListener(new ConnectionCreationListener() {
049            public void connectionCreated(XMPPConnection connection) {
050                getInstanceFor(connection);
051            }
052        });
053    }
054
055    public static void setAutoEnable(boolean autoEnable) {
056        EntityTimeManager.autoEnable = autoEnable;
057    }
058
059    public synchronized static EntityTimeManager getInstanceFor(XMPPConnection connection) {
060        EntityTimeManager entityTimeManager = INSTANCES.get(connection);
061        if (entityTimeManager == null) {
062            entityTimeManager = new EntityTimeManager(connection);
063        }
064        return entityTimeManager;
065    }
066
067    private boolean enabled = false;
068
069    private EntityTimeManager(XMPPConnection connection) {
070        super(connection);
071        INSTANCES.put(connection, this);
072        if (autoEnable)
073            enable();
074
075        connection.addPacketListener(new PacketListener() {
076            @Override
077            public void processPacket(Packet packet) throws NotConnectedException {
078                if (!enabled)
079                    return;
080                connection().sendPacket(Time.createResponse(packet));
081            }
082        }, TIME_PACKET_FILTER);
083    }
084
085    public synchronized void enable() {
086        if (enabled)
087            return;
088        ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection());
089        sdm.addFeature(Time.NAMESPACE);
090        enabled = true;
091    }
092
093    public synchronized void disable() {
094        if (!enabled)
095            return;
096        ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection());
097        sdm.removeFeature(Time.NAMESPACE);
098        enabled = false;
099    }
100
101    public boolean isTimeSupported(String jid) throws NoResponseException, XMPPErrorException, NotConnectedException  {
102        return ServiceDiscoveryManager.getInstanceFor(connection()).supportsFeature(jid, Time.NAMESPACE);
103    }
104
105    public Time getTime(String jid) throws NoResponseException, XMPPErrorException, NotConnectedException {
106        if (!isTimeSupported(jid))
107            return null;
108
109        Time request = new Time();
110        Time response = (Time) connection().createPacketCollectorAndSend(request).nextResultOrThrow();
111        return response;
112    }
113}