/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Distributable under LGPL license. * See terms of license at gnu.org. */ package net.java.sip.communicator.impl.protocol.jabber; import java.util.*; import net.java.sip.communicator.impl.protocol.jabber.extensions.notification.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.service.protocol.event.*; import net.java.sip.communicator.util.*; import org.jivesoftware.smack.*; import org.jivesoftware.smack.filter.*; import org.jivesoftware.smack.packet.IQ.Type; import org.jivesoftware.smack.packet.*; import org.jivesoftware.smack.provider.*; /** * Provides notification for generic events with name and value, also * option to generate such events. * * @author Damian Minkov * @author Emil Ivov */ public class OperationSetGenericNotificationsJabberImpl implements OperationSetGenericNotifications, PacketListener { /** * Our class logger */ private static final Logger logger = Logger.getLogger(OperationSetGenericNotificationsJabberImpl.class); /** * The provider that created us. */ private final ProtocolProviderServiceJabberImpl jabberProvider; /** * A reference to the persistent presence operation set that we use * to match incoming event to Contacts and vice versa. */ private OperationSetPersistentPresenceJabberImpl opSetPersPresence = null; /** * Listeners that would receive event notifications for * new event notifications */ private final Map> genericEventListeners = new HashMap>(); /** * Creates an instance of this operation set. * @param provider a reference to the ProtocolProviderServiceImpl * that created us and that we'll use for retrieving the underlying aim * connection. */ OperationSetGenericNotificationsJabberImpl( ProtocolProviderServiceJabberImpl provider ) { this.jabberProvider = provider; provider.addRegistrationStateChangeListener( new RegistrationStateListener()); // register the notification event Extension in the smack library ProviderManager.getInstance() .addIQProvider(NotificationEventIQ.ELEMENT_NAME, NotificationEventIQ.NAMESPACE, new NotificationEventIQProvider()); } /** * Generates new event notification. * * @param contact the contact to receive the notification. * @param eventName the event name of the notification. * @param eventValue the event value of the notification. */ public void notifyForEvent( Contact contact, String eventName, String eventValue) { // if we are not registered do nothing if(!jabberProvider.isRegistered()) { if (logger.isTraceEnabled()) logger.trace("provider not registered. " +"won't send keep alive. acc.id=" + jabberProvider.getAccountID() .getAccountUniqueID()); return; } NotificationEventIQ newEvent = new NotificationEventIQ(); newEvent.setEventName(eventName); newEvent.setEventValue(eventValue); newEvent.setTo(contact.getAddress()); newEvent.setEventSource(jabberProvider.getOurJID()); jabberProvider.getConnection().sendPacket(newEvent); } /** * Generates new generic event notification and send it to the * supplied contact. * @param jid the contact jid which will receive the event notification. * @param eventName the event name of the notification. * @param eventValue the event value of the notification. */ public void notifyForEvent( String jid, String eventName, String eventValue) { this.notifyForEvent(jid, eventName, eventValue, null); } /** * Generates new generic event notification and send it to the * supplied contact. * @param jid the contact jid which will receive the event notification. * @param eventName the event name of the notification. * @param eventValue the event value of the notification. * @param source the source that will be reported in the event. */ public void notifyForEvent( String jid, String eventName, String eventValue, String source) { // if we are not registered do nothing if(!jabberProvider.isRegistered()) { if (logger.isTraceEnabled()) logger.trace("provider not registered. " +"won't send keep alive. acc.id=" + jabberProvider.getAccountID() .getAccountUniqueID()); return; } //try to convert the jid to a full jid String fullJid = jabberProvider.getFullJid(jid); if( fullJid != null ) jid = fullJid; NotificationEventIQ newEvent = new NotificationEventIQ(); newEvent.setEventName(eventName); newEvent.setEventValue(eventValue); newEvent.setTo(jid); if(source != null) newEvent.setEventSource(source); else newEvent.setEventSource(jabberProvider.getOurJID()); jabberProvider.getConnection().sendPacket(newEvent); } /** * Registers a GenericEventListener with this * operation set so that it gets notifications for new * event notifications. * * @param eventName register the listener for certain event name. * @param listener the GenericEventListener * to register. */ public void addGenericEventListener( String eventName, GenericEventListener listener) { synchronized (genericEventListeners) { List l = this.genericEventListeners.get(eventName); if(l == null) { l = new ArrayList(); this.genericEventListeners.put(eventName, l); } if(!l.contains(listener)) l.add(listener); } } /** * Unregisters listener so that it won't receive any further * notifications upon new event notifications. * * @param eventName unregister the listener for certain event name. * @param listener the GenericEventListener * to unregister. */ public void removeGenericEventListener( String eventName, GenericEventListener listener) { synchronized (genericEventListeners) { List listenerList = this.genericEventListeners.get(eventName); if(listenerList != null) listenerList.remove(listener); } } /** * Process the next packet sent to this packet listener.

*

* * @param packet the packet to process. */ public void processPacket(Packet packet) { if(packet != null && !(packet instanceof NotificationEventIQ)) return; NotificationEventIQ notifyEvent = (NotificationEventIQ)packet; if(logger.isDebugEnabled()) { if (logger.isDebugEnabled()) logger.debug("Received notificationEvent from " + notifyEvent.getFrom() + " msg : " + notifyEvent.toXML()); } //do not notify String fromUserID = org.jivesoftware.smack.util.StringUtils.parseBareAddress( notifyEvent.getFrom()); Contact sender = opSetPersPresence.findContactByID(fromUserID); if(sender == null) sender = opSetPersPresence.createVolatileContact( notifyEvent.getFrom()); if(notifyEvent.getType() == Type.GET) fireNewEventNotification( sender, notifyEvent.getEventName(), notifyEvent.getEventValue(), notifyEvent.getEventSource(), true); else if(notifyEvent.getType() == Type.ERROR) fireNewEventNotification( sender, notifyEvent.getEventName(), notifyEvent.getEventValue(), notifyEvent.getEventSource(), false); } /** * Fires new notification event. * * @param from common from Contact. * @param eventName the event name. * @param eventValue the event value. * @param source the name of the contact sending the notification. * @param incoming indicates whether the event we are dispatching * corresponds to an incoming notification or an error report indicating * that an outgoing notification has failed. */ private void fireNewEventNotification( Contact from, String eventName, String eventValue, String source, boolean incoming) { String sourceUserID = org.jivesoftware.smack.util.StringUtils.parseBareAddress( source); Contact sourceContact = opSetPersPresence.findContactByID(sourceUserID); if(sourceContact == null) sourceContact = opSetPersPresence .createVolatileContact(source); GenericEvent event = new GenericEvent( jabberProvider, from, eventName, eventValue, sourceContact); Iterable listeners; synchronized (genericEventListeners) { List ls = genericEventListeners.get(eventName); if(ls == null) return; listeners = new ArrayList(ls); } for (GenericEventListener listener : listeners) { if(incoming) listener.notificationReceived(event); else listener.notificationDeliveryFailed(event); } } /** * Our listener that will tell us when we're registered to */ private class RegistrationStateListener implements RegistrationStateChangeListener { /** * The method is called by a ProtocolProvider implementation whenever * a change in the registration state of the corresponding provider had * occurred. * @param evt ProviderStatusChangeEvent the event describing the status * change. */ public void registrationStateChanged(RegistrationStateChangeEvent evt) { if (evt.getNewState() == RegistrationState.REGISTERED) { OperationSetGenericNotificationsJabberImpl.this.opSetPersPresence = (OperationSetPersistentPresenceJabberImpl) jabberProvider.getOperationSet( OperationSetPersistentPresence.class); if(jabberProvider.getConnection() != null) { jabberProvider.getConnection().addPacketListener( OperationSetGenericNotificationsJabberImpl.this, new PacketTypeFilter(NotificationEventIQ.class)); } } else if(evt.getNewState() == RegistrationState.UNREGISTERED || evt.getNewState() == RegistrationState.CONNECTION_FAILED || evt.getNewState() == RegistrationState.AUTHENTICATION_FAILED) { if(jabberProvider.getConnection() != null) { jabberProvider.getConnection().removePacketListener( OperationSetGenericNotificationsJabberImpl.this); } OperationSetGenericNotificationsJabberImpl.this.opSetPersPresence = null; } } } }