Introduce sending/receiving generic events operation set and its implementation for jabber protocol.

cusax-fix
Damian Minkov 15 years ago
parent 564187c04f
commit f73d03ef5e

@ -0,0 +1,314 @@
/*
* SIP Communicator, 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 net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.impl.protocol.jabber.extensions.notification.*;
import net.java.sip.communicator.util.*;
import org.jivesoftware.smack.*;
import org.jivesoftware.smack.filter.*;
import org.jivesoftware.smack.packet.*;
import org.jivesoftware.smack.provider.*;
import java.util.*;
/**
* Provides notification for generic events with name and value, also
* option to generate such events.
*
* @author Damian Minkov
*/
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 <tt>Contact</tt>s and vice versa.
*/
private OperationSetPersistentPresenceJabberImpl opSetPersPresence = null;
/**
* Listeners that would receive event notifications for
* new event notifications
*/
private final Map<String, List<GenericEventListener>>
genericEventListeners
= new HashMap<String,
List<GenericEventListener>>();
/**
* Creates an instance of this operation set.
* @param provider a reference to the <tt>ProtocolProviderServiceImpl</tt>
* 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)
{
// 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(jid);
newEvent.setEventSource(jabberProvider.getOurJID());
jabberProvider.getConnection().sendPacket(newEvent);
}
/**
* Registers a <tt>GenericEventListener</tt> 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 <tt>GenericEventListener</tt>
* to register.
*/
public void addGenericEventListener(
String eventName,
GenericEventListener listener)
{
synchronized (genericEventListeners)
{
List<GenericEventListener> l =
this.genericEventListeners.get(eventName);
if(l == null)
{
l = new ArrayList<GenericEventListener>();
this.genericEventListeners.put(eventName, l);
}
if(!l.contains(listener))
l.add(listener);
}
}
/**
* Unregisters <tt>listener</tt> 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 <tt>GenericEventListener</tt>
* to unregister.
*/
public void removeGenericEventListener(
String eventName,
GenericEventListener listener)
{
synchronized (genericEventListeners)
{
List l = this.genericEventListeners.get(eventName);
if(l != null)
this.genericEventListeners.remove(listener);
}
}
/**
* Process the next packet sent to this packet listener.<p>
* <p/>
*
* @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());
}
String fromUserID
= org.jivesoftware.smack.util.StringUtils.parseBareAddress(
notifyEvent.getFrom());
Contact sender = opSetPersPresence.findContactByID(fromUserID);
if(sender == null)
sender = opSetPersPresence.createVolatileContact(fromUserID);
fireNewEventNotification(
sender,
notifyEvent.getEventName(),
notifyEvent.getEventValue(),
notifyEvent.getEventSource());
}
/**
* Fires new notification event.
* @param from common from <tt>Contact</tt>.
* @param eventName the event name.
* @param eventValue the event value.
*/
private void fireNewEventNotification(
Contact from,
String eventName,
String eventValue,
String source)
{
String sourceUserID
= org.jivesoftware.smack.util.StringUtils.parseBareAddress(
source);
Contact sourceContact =
opSetPersPresence.findContactByID(sourceUserID);
if(sourceContact == null)
sourceContact = opSetPersPresence
.createVolatileContact(sourceUserID);
GenericEvent
event = new GenericEvent(
jabberProvider, from, eventName, eventValue, sourceContact);
Iterable<GenericEventListener> listeners;
synchronized (genericEventListeners)
{
List<GenericEventListener> ls =
genericEventListeners.get(eventName);
if(ls == null)
return;
listeners = new ArrayList<GenericEventListener>(ls);
}
for (GenericEventListener listener : listeners)
{
listener.notify(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;
}
}
}
}

@ -1166,6 +1166,10 @@ protected void initialize(String screenname,
OperationSetContactCapabilities.class,
opsetContactCapabilities);
addSupportedOperationSet(
OperationSetGenericNotifications.class,
new OperationSetGenericNotificationsJabberImpl(this));
isInitialized = true;
}
}

@ -0,0 +1,149 @@
/*
* SIP Communicator, 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.extensions.notification;
import org.jivesoftware.smack.packet.*;
import org.jivesoftware.smack.util.*;
/**
* Notification Event. Events are send to notify for some event
* holding a value.
*
* @author Damian Minkov
*/
public class NotificationEventIQ
extends IQ
{
/**
* The namespace that input notification belongs to.
*/
public static final String NAMESPACE = "sip-communicator:iq:notification";
/**
* The name of the element that contains the notification event data.
*/
public static final String ELEMENT_NAME = "notification";
/**
* The name of the argument that contains the event name.
*/
static final String EVENT_NAME = "name";
/**
* The name of the argument that contains the event value.
*/
static final String EVENT_VALUE = "value";
/**
* The name of the argument that contains the event source.
*/
static final String EVENT_SOURCE = "source";
/**
* Current notification event name.
*/
private String eventName;
/**
* Current notification event value.
*/
private String eventValue;
/**
* Current notification event source.
*/
private String eventSource;
/**
* Returns the sub-element XML section of the IQ packet,
* or <tt>null</tt> if there isn't one. Packet extensions <b>must</b>
* be included, if any are defined.<p>
* <p/>
* Extensions of this class must override this method.
*
* @return the child element section of the IQ XML.
*/
@Override
public String getChildElementXML()
{
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).
append(" xmlns=\"").append(NAMESPACE).
append("\">");
buf.append("<").append(EVENT_NAME).append(">").
append(StringUtils.escapeForXML(this.getEventName()))
.append("</").append(EVENT_NAME).append(">");
buf.append("<").
append(EVENT_VALUE).append(">").
append(StringUtils.escapeForXML(this.getEventValue()))
.append("</").append(EVENT_VALUE).append(">");
buf.append("<").
append(EVENT_SOURCE).append(">").
append(StringUtils.escapeForXML(this.getEventSource()))
.append("</").append(EVENT_SOURCE).append(">");
buf.append("</").append(ELEMENT_NAME).append(">");
return buf.toString();
}
/**
* Current notification event name.
* @return current event name.
*/
public String getEventName()
{
return eventName;
}
/**
* Sets event new name.
* @param eventName new event name.
*/
public void setEventName(String eventName)
{
this.eventName = eventName;
}
/**
* Current notification event value.
* @return current event value.
*/
public String getEventValue()
{
return eventValue;
}
/**
* Sets event new value.
* @param eventValue new event value.
*/
public void setEventValue(String eventValue)
{
this.eventValue = eventValue;
}
/**
* Current notification event source.
* @return the current notification event source.
*/
public String getEventSource()
{
return eventSource;
}
/**
* Sets event source new value.
* @param eventSource value.
*/
public void setEventSource(String eventSource)
{
this.eventSource = eventSource;
}
}

@ -0,0 +1,67 @@
/*
* SIP Communicator, 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.extensions.notification;
import org.jivesoftware.smack.packet.*;
import org.jivesoftware.smack.provider.*;
import org.xmlpull.v1.*;
/**
* The NotificationEventIQProvider parses Notification Event packets.
*
* @author Damian Minkov
*/
public class NotificationEventIQProvider
implements IQProvider
{
/**
* Parse the IQ sub-document and create an IQ instance. Each IQ must have a
* single child element. At the beginning of the method call, the xml parser
* will be positioned at the opening tag of the IQ child element. At the end
* of the method call, the parser <b>must</b> be positioned on the closing
* tag of the child element.
*
* @param parser an XML parser.
* @return a new IQ instance.
* @throws Exception if an error occurs parsing the XML.
*/
public IQ parseIQ(XmlPullParser parser)
throws Exception
{
NotificationEventIQ result = new NotificationEventIQ();
boolean done = false;
while (!done)
{
int eventType = parser.next();
if(eventType == XmlPullParser.START_TAG)
{
if(parser.getName().equals(NotificationEventIQ.EVENT_NAME))
{
result.setEventName(parser.nextText());
}
else if(parser.getName().equals(NotificationEventIQ.EVENT_VALUE))
{
result.setEventValue(parser.nextText());
}
else if(parser.getName().equals(NotificationEventIQ.EVENT_SOURCE))
{
result.setEventSource(parser.nextText());
}
}
else if(eventType == XmlPullParser.END_TAG)
{
if(parser.getName().equals(NotificationEventIQ.ELEMENT_NAME))
{
done = true;
}
}
}
return result;
}
}

@ -0,0 +1,68 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.service.protocol;
import net.java.sip.communicator.service.protocol.event.*;
/**
* Provides notification for custom/generic events and possibility to generate
* such events.
*
* @author Damian Minkov
*/
public interface OperationSetGenericNotifications
extends OperationSet
{
/**
* Generates new generic event notification and send it to the
* supplied contact.
* @param contact the contact to receive the event 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);
/**
* 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);
/**
* Registers a <tt>GenericEventListener</tt> 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 <tt>GenericEventListener</tt>
* to register.
*/
public void addGenericEventListener(
String eventName,
GenericEventListener listener);
/**
* Unregisters <tt>listener</tt> 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 <tt>GenericEventListener</tt>
* to unregister.
*/
public void removeGenericEventListener(
String eventName,
GenericEventListener listener);
}

@ -0,0 +1,121 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.service.protocol.event;
import net.java.sip.communicator.service.protocol.*;
import java.util.*;
/**
* <tt>GenericEvent</tt>s indicate reception of an new generic event.
*
* @author Damian Minkov
*/
public class GenericEvent
extends EventObject
{
/**
* The contact which is the source of this event.
*/
private Contact from;
/**
* The event name.
*/
private String eventName;
/**
* The event value.
*/
private String eventValue;
/**
* The source contact for this event.
*/
private Contact sourceContact;
/**
* Constructs a GenericEvent.
*
* @param sourceProtocolProvider The object on which the Event initially occurred.
* @param from the contact from which this event is coming from.
* @param eventName the event name.
* @param eventValue the event value.
* @param sourceContact contact for this event.
* @throws IllegalArgumentException if source is null.
*/
public GenericEvent(ProtocolProviderService sourceProtocolProvider,
Contact from,
String eventName,
String eventValue,
Contact sourceContact)
{
super(sourceProtocolProvider);
this.from = from;
this.eventName = eventName;
this.eventValue = eventValue;
this.sourceContact = sourceContact;
}
/**
* The event name.
* @return the event name.
*/
public String getEventName()
{
return eventName;
}
/**
* The event value.
* @return the event value.
*/
public String getEventValue()
{
return eventValue;
}
/**
* The contact which is the source of this event.
* @return the contact which is the source of this event.
*/
public Contact getFrom()
{
return from;
}
/**
* Returns the <tt>ProtocolProviderService</tt> which originated this event.
*
* @return the source <tt>ProtocolProviderService</tt>
*/
public ProtocolProviderService getSourceProvider()
{
return (ProtocolProviderService) getSource();
}
/**
* Returns a String representation of this GenericEvent.
*
* @return A a String representation of this GenericEvent.
*/
public String toString()
{
return "GenericEvent from:" + from + " - eventName:"+ eventName
+ " eventValue:" + eventValue;
}
/**
* Returns The source contact for this event.
* @return the event source contact.
*/
public Contact getSourceContact()
{
return sourceContact;
}
}

@ -0,0 +1,22 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.service.protocol.event;
/**
* A listener that would gather and notify for incoming generic
* events.
*
* @author Damian Minkov
*/
public interface GenericEventListener
{
/**
* Notify for incoming <tt>GenericEvent</tt>.
* @param event the incoming event.
*/
public void notify(GenericEvent event);
}
Loading…
Cancel
Save