001/**
002 *
003 * Copyright 2003-2007 Jive Software.
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 */
017
018package org.jivesoftware.smackx.pep;
019
020import java.util.ArrayList;
021import java.util.List;
022
023import org.jivesoftware.smack.PacketListener;
024import org.jivesoftware.smack.SmackException.NotConnectedException;
025import org.jivesoftware.smack.XMPPConnection;
026import org.jivesoftware.smack.filter.PacketExtensionFilter;
027import org.jivesoftware.smack.filter.PacketFilter;
028import org.jivesoftware.smack.packet.Message;
029import org.jivesoftware.smack.packet.Packet;
030import org.jivesoftware.smack.packet.IQ.Type;
031import org.jivesoftware.smackx.pep.packet.PEPEvent;
032import org.jivesoftware.smackx.pep.packet.PEPItem;
033import org.jivesoftware.smackx.pep.packet.PEPPubSub;
034
035/**
036 *
037 * Manages Personal Event Publishing (XEP-163). A PEPManager provides a high level access to
038 * pubsub personal events. It also provides an easy way
039 * to hook up custom logic when events are received from another XMPP client through PEPListeners.
040 * 
041 * Use example:
042 * 
043 * <pre>
044 *   PEPManager pepManager = new PEPManager(smackConnection);
045 *   pepManager.addPEPListener(new PEPListener() {
046 *       public void eventReceived(String inFrom, PEPEvent inEvent) {
047 *           LOGGER.debug("Event received: " + inEvent);
048 *       }
049 *   });
050 *
051 *   PEPProvider pepProvider = new PEPProvider();
052 *   pepProvider.registerPEPParserExtension("http://jabber.org/protocol/tune", new TuneProvider());
053 *   ProviderManager.getInstance().addExtensionProvider("event", "http://jabber.org/protocol/pubsub#event", pepProvider);
054 *   
055 *   Tune tune = new Tune("jeff", "1", "CD", "My Title", "My Track");
056 *   pepManager.publish(tune);
057 * </pre>
058 * 
059 * @author Jeff Williams
060 */
061public class PEPManager {
062
063    private List<PEPListener> pepListeners = new ArrayList<PEPListener>();
064
065    private XMPPConnection connection;
066
067    private PacketFilter packetFilter = new PacketExtensionFilter("event", "http://jabber.org/protocol/pubsub#event");
068    private PacketListener packetListener;
069
070    /**
071     * Creates a new PEP exchange manager.
072     *
073     * @param connection a XMPPConnection which is used to send and receive messages.
074     */
075    public PEPManager(XMPPConnection connection) {
076        this.connection = connection;
077        init();
078    }
079
080    /**
081     * Adds a listener to PEPs. The listener will be fired anytime PEP events
082     * are received from remote XMPP clients.
083     *
084     * @param pepListener a roster exchange listener.
085     */
086    public void addPEPListener(PEPListener pepListener) {
087        synchronized (pepListeners) {
088            if (!pepListeners.contains(pepListener)) {
089                pepListeners.add(pepListener);
090            }
091        }
092    }
093
094    /**
095     * Removes a listener from PEP events.
096     *
097     * @param pepListener a roster exchange listener.
098     */
099    public void removePEPListener(PEPListener pepListener) {
100        synchronized (pepListeners) {
101            pepListeners.remove(pepListener);
102        }
103    }
104
105    /**
106     * Publish an event.
107     * 
108     * @param item the item to publish.
109     * @throws NotConnectedException 
110     */
111    public void publish(PEPItem item) throws NotConnectedException {
112        // Create a new message to publish the event.
113        PEPPubSub pubSub = new PEPPubSub(item);
114        pubSub.setType(Type.SET);
115        //pubSub.setFrom(connection.getUser());
116 
117        // Send the message that contains the roster
118        connection.sendPacket(pubSub);
119    }
120
121    /**
122     * Fires roster exchange listeners.
123     */
124    private void firePEPListeners(String from, PEPEvent event) {
125        PEPListener[] listeners = null;
126        synchronized (pepListeners) {
127            listeners = new PEPListener[pepListeners.size()];
128            pepListeners.toArray(listeners);
129        }
130        for (int i = 0; i < listeners.length; i++) {
131            listeners[i].eventReceived(from, event);
132        }
133    }
134
135    private void init() {
136        // Listens for all roster exchange packets and fire the roster exchange listeners.
137        packetListener = new PacketListener() {
138            public void processPacket(Packet packet) {
139                Message message = (Message) packet;
140                PEPEvent event = (PEPEvent) message.getExtension("event", "http://jabber.org/protocol/pubsub#event");
141                // Fire event for roster exchange listeners
142                firePEPListeners(message.getFrom(), event);
143            };
144
145        };
146        connection.addPacketListener(packetListener, packetFilter);
147    }
148
149    public void destroy() {
150        if (connection != null)
151            connection.removePacketListener(packetListener);
152
153    }
154
155    protected void finalize() throws Throwable {
156        destroy();
157        super.finalize();
158    }
159}