/* * 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 java.util.*; import net.java.sip.communicator.impl.protocol.jabber.extensions.version.*; import net.java.sip.communicator.impl.protocol.jabber.extensions.whiteboard.*; import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.service.protocol.whiteboardobjects.*; import org.jivesoftware.smack.*; import org.jivesoftware.smack.filter.*; import org.jivesoftware.smack.packet.*; import org.jivesoftware.smack.util.*; import org.jivesoftware.smackx.*; import net.java.sip.communicator.service.protocol.event.*; import net.java.sip.communicator.util.*; /** * A representation of a WhiteboardSession. * * @author Julien Waechter * @author Yana Stamcheva */ public class WhiteboardSessionJabberImpl implements WhiteboardParticipantListener, WhiteboardSession { private static final Logger logger = Logger.getLogger(WhiteboardSessionJabberImpl.class); /** * A list of listeners registered for message events. */ private Vector messageListeners = new Vector(); /** * A list containing all WhiteboardParticipants of this session. */ private Hashtable wbParticipants = new Hashtable(); /** * The state that this white-board is currently in. */ private WhiteboardSessionState whiteboardState = WhiteboardSessionState.WHITEBOARD_INITIALIZATION; /** * The provider that created us. */ private ProtocolProviderServiceJabberImpl jabberProvider = null; /** * An identifier uniquely representing the white-board. */ private String whiteboardID = null; /** * A list of all listeners currently registered for * WhiteboardChangeEvents */ private Vector whiteboardListeners = new Vector(); /** * Stores all white board objects contained in this session. */ private Vector whiteboardObjects = new Vector(); /** * The OperationSet charged with the whiteboarding. */ private OperationSetWhiteboardingJabberImpl whiteboardOpSet; /** * The corresponding smack chat. */ private Chat smackChat; /** * WhiteboardSessionJabberImpl constructor. * * @param sourceProvider Jabber protocol provider * @param opSet the whiteboard operation set */ public WhiteboardSessionJabberImpl( ProtocolProviderServiceJabberImpl sourceProvider, OperationSetWhiteboardingJabberImpl opSet) { this.jabberProvider = sourceProvider; this.whiteboardOpSet = opSet; //create the UID this.whiteboardID = String.valueOf(System.currentTimeMillis()) + String.valueOf(super.hashCode()); } /** * Returns an iterator over all white-board participants. * * @return an Iterator over all participants currently involved in the * white-board. */ public Iterator getWhiteboardParticipants() { return new LinkedList(wbParticipants.values()).iterator(); } /** * Returns the number of participants currently associated * with this white-board session. * * @return an int indicating the number of participants currently * associated with this white-board. */ public int getWhiteboardParticipantsCount() { return wbParticipants.size(); } /** * Joins this white-board with the nickname of the local user so that the * user would start receiving events and WhiteboardObject for it. * * @throws OperationFailedException with the corresponding code if an error * occurs while joining the room. */ public void join() throws OperationFailedException { PacketExtensionFilter filterWhiteboard = new PacketExtensionFilter( WhiteboardObjectPacketExtension.NAMESPACE); this.jabberProvider.getConnection().addPacketListener( new WhiteboardSmackMessageListener(), filterWhiteboard); this.whiteboardOpSet.fireWhiteboardSessionPresenceEvent( this, WhiteboardSessionPresenceChangeEvent.LOCAL_USER_JOINED, null); } /** * Joins this white-board so that the user would start receiving events and * WhiteboardObject for it. The method uses the nickname of the local user * and the specified password in order to enter the white-board session. * * @param password the password to use when authenticating on the * white-board session. * @throws OperationFailedException with the corresponding code if an error * occurs while joining the room. */ public void join(byte[] password) throws OperationFailedException { } /** * Returns true if the local user is currently in the white-board session * (after white-boarding one of the {@link #join(String)} methods). * * @return true if currently we're currently in this white-board and false * otherwise. */ public boolean isJoined() { return true; } /** * Leave this whiteboard. Once this method is whiteboarded, the user won't * be listed as a member of the whiteboard any more and no further * whiteboard events will be delivered. Depending on the underlying protocol * and implementation leave() might cause the room to be destroyed if it has * been created by the local user. */ public void leave() { try { assertConnected(); org.jivesoftware.smack.packet.Message msg = new org.jivesoftware.smack.packet.Message(); WhiteboardSessionPacketExtension extension = new WhiteboardSessionPacketExtension( this, jabberProvider.getAccountID().getAccountAddress(), WhiteboardSessionPacketExtension.ACTION_LEAVE); msg.addExtension(extension); msg.addExtension(new Version()); MessageEventManager.addNotificationsRequests( msg, true, // offline false, // delivered false, // displayed true); // composing smackChat.sendMessage(msg); } catch (XMPPException ex) { ex.printStackTrace(); logger.error("message not send", ex); } // Inform all interested listeners that user has left the white board. whiteboardOpSet.fireWhiteboardSessionPresenceEvent( this, WhiteboardSessionPresenceChangeEvent.LOCAL_USER_LEFT, null); } /** * Invites another user to this room. *
* If the room is password-protected, the invitee will receive a password to
* use to join the room. If the room is members-only, the the invitee may
* be added to the member list.
*
* @param contactAddress the address of the user to invite to the room.
* (one may also invite users not on their contact list).
*/
public void invite(String contactAddress)
{
OperationSetPersistentPresenceJabberImpl presenceOpSet
= (OperationSetPersistentPresenceJabberImpl) jabberProvider
.getOperationSet(OperationSetPresence.class);
// If there's no presence operation set we return, because there's
// not contact to associate the event with.
if (presenceOpSet == null)
return;
ContactJabberImpl sourceContact
= (ContactJabberImpl) presenceOpSet.findContactByID(contactAddress);
if (sourceContact == null)
{
sourceContact = presenceOpSet.createVolatileContact(contactAddress);
}
this.addWhiteboardParticipant(
new WhiteboardParticipantJabberImpl(sourceContact, this));
try
{
sendWhiteboardObject(
createWhiteboardObject(WhiteboardObjectLine.NAME));
}
catch (OperationFailedException e)
{
logger.error("Could not send an invite whiteboard object.", e);
}
}
/**
* returns the current WhiteboardSession
* @return current WhiteboardSession
*/
public WhiteboardSession getWhiteboardSession()
{
return this;
}
/**
* Verifies whether the whiteboard participant has entered a state.
*
* @param evt The WhiteboardParticipantChangeEvent instance
* containing the source event as well as its previous and its new status.
*/
public void participantStateChanged(WhiteboardParticipantChangeEvent evt)
{
if (((WhiteboardParticipantState) evt.getNewValue())
== WhiteboardParticipantState.DISCONNECTED
|| ((WhiteboardParticipantState) evt.getNewValue())
== WhiteboardParticipantState.FAILED)
{
removeWhiteboardParticipant((WhiteboardParticipantJabberImpl) evt
.getSourceWhiteboardParticipant());
}
}
/**
* Indicates that a change has occurred in the display name of the source
* WhiteboardParticipant.
*
* @param evt The WhiteboardParticipantChangeEvent instance
* containing the source event as well as its previous and its new display
* names.
*/
public void participantDisplayNameChanged(
WhiteboardParticipantChangeEvent evt)
{
}
/**
* Indicates that a change has occurred in the address of the source
* WhiteboardParticipant.
*
* @param evt The WhiteboardParticipantChangeEvent instance
* containing the source event as well as its previous and its new address.
*/
public void participantAddressChanged(WhiteboardParticipantChangeEvent evt)
{
}
/**
* Indicates that a change has occurred in the transport address that we
* use to communicate with the participant.
*
* @param evt The WhiteboardParticipantChangeEvent instance
* containing the source event as well as its previous and its new transport
* address.
*/
public void participantTransportAddressChanged(
WhiteboardParticipantChangeEvent evt)
{
}
/**
* Indicates that a change has occurred in the image of the source
* WhiteboardParticipant.
*
* @param evt The WhiteboardParticipantChangeEvent instance
* containing the source event as well as its previous and its new image.
*/
public void participantImageChanged(WhiteboardParticipantChangeEvent evt)
{
}
/**
* Adds wbParticipant to the list of participants in this
* white-board.
* If the white-board participant is already included in the white-board,
* the method has no effect.
*
* @param wbParticipant the new WhiteboardParticipant
*/
public void addWhiteboardParticipant(WhiteboardParticipant wbParticipant)
{
if (wbParticipants.contains(wbParticipant))
return;
wbParticipant.addWhiteboardParticipantListener(this);
this.wbParticipants.put(
wbParticipant.getContactAddress(), wbParticipant);
this.smackChat = jabberProvider.getConnection().getChatManager()
.createChat(wbParticipant.getContactAddress(), null);
fireWhiteboardParticipantEvent(wbParticipant,
WhiteboardParticipantEvent.WHITEBOARD_PARTICIPANT_ADDED);
}
/**
* Removes whiteboardParticipant from the list of participants in
* this whiteboard. The method has no effect if there was no
* such participant in the whiteboard.
*
* @param wbParticipant the WhiteboardParticipant leaving the
* whiteboard;
*/
public void removeWhiteboardParticipant(WhiteboardParticipant wbParticipant)
{
if (!wbParticipants.contains(wbParticipant))
return;
this.wbParticipants.remove(wbParticipant);
if (wbParticipant instanceof WhiteboardParticipantJabberImpl)
((WhiteboardParticipantJabberImpl) wbParticipant)
.setWhiteboardSession(null);
wbParticipant.removeWhiteboardParticipantListener(this);
fireWhiteboardParticipantEvent(wbParticipant,
WhiteboardParticipantEvent.WHITEBOARD_PARTICIPANT_REMOVED);
if (wbParticipants.size() == 0)
setWhiteboardSessionState(WhiteboardSessionState.WHITEBOARD_ENDED);
}
/**
* Sets the state of this whiteboard and fires a whiteboard change event
* notifying registered listeners for the change.
*
* @param newState a reference to the WhiteboardState instance that
* the whiteboard is to enter.
*/
public void setWhiteboardSessionState(WhiteboardSessionState newState)
{
WhiteboardSessionState oldState = getWhiteboardSessionState();
if (oldState == newState)
return;
this.whiteboardState = newState;
fireWhiteboardChangeEvent(
WhiteboardChangeEvent.WHITEBOARD_STATE_CHANGE, oldState, newState);
}
/**
* Returns the state that this whiteboard is currently in.
* @return a reference to the WhiteboardState
* instance that the whiteboard is currently in.
*/
public WhiteboardSessionState getWhiteboardSessionState()
{
return whiteboardState;
}
/**
* Registers listener so that it would receive events every time a
* new WhiteboardObject is received on this whiteboard.
*
*
* @param listener a WhiteboardObjectListener that would be
* notified every time a new WhiteboardObject
* is received on this whiteboard.
*/
public void addWhiteboardObjectListener(WhiteboardObjectListener listener)
{
synchronized (messageListeners)
{
if (!messageListeners.contains(listener))
{
this.messageListeners.add(listener);
}
}
}
/**
* Removes listener so that it won't receive
* any further WhiteboardObject events from this room.
*
*
* @param listener the WhiteboardObjectListener
* to remove from this room
*/
public void removeWhiteboardObjectListener(
WhiteboardObjectListener listener)
{
synchronized (messageListeners)
{
this.messageListeners.remove(listener);
}
}
/**
* Create a WhiteboardObject instance with the specified type. This method
* only creates the object locally and it would not be visible to other
* session participants until it is resolved with the
* sendWhiteboardObject(WhiteboardObject) method.
*
* @param name the name of the object to create (should be one of the
* WhiteboardObjectXXX.NAME fields).
*
* @return the newly created WhiteboardObject with an id
*/
public WhiteboardObject createWhiteboardObject(String name)
{
WhiteboardObjectJabberImpl wbObj = null;
logger.debug("[log] WhiteboardObjectXXX.NAME: " + name);
if (name.equals(WhiteboardObjectPath.NAME))
{
wbObj = new WhiteboardObjectPathJabberImpl();
}
else if (name.equals(WhiteboardObjectPolyLine.NAME))
{
wbObj = new WhiteboardObjectPolyLineJabberImpl();
}
else if (name.equals(WhiteboardObjectPolygon.NAME))
{
wbObj = new WhiteboardObjectPolygonJabberImpl();
}
else if (name.equals(WhiteboardObjectLine.NAME))
{
wbObj = new WhiteboardObjectLineJabberImpl();
}
else if (name.equals(WhiteboardObjectRect.NAME))
{
wbObj = new WhiteboardObjectRectJabberImpl();
}
else if (name.equals(WhiteboardObjectCircle.NAME))
{
wbObj = new WhiteboardObjectCircleJabberImpl();
}
else if (name.equals(WhiteboardObjectText.NAME))
{
wbObj = new WhiteboardObjectTextJabberImpl();
}
else if (name.equals(WhiteboardObjectImage.NAME))
{
wbObj = new WhiteboardObjectImageJabberImpl();
}
whiteboardObjects.add(wbObj);
return wbObj;
}
/**
* Returns the id of the specified Whiteboard.
*
* @return a String uniquely identifying the whiteboard.
*/
public String getWhiteboardID()
{
return whiteboardID;
}
/**
* Determines wheter the protocol provider (or the protocol itself) support
* sending and receiving offline messages. Most often this method would
* return true for protocols that support offline messages and false for
* those that don't. It is however possible for a protocol to support these
* messages and yet have a particular account that does not (i.e. feature
* not enabled on the protocol server). In cases like this it is possible
* for this method to return true even when offline messaging is not
* supported, and then have the sendMessage method throw an
* OperationFailedException with code - OFFLINE_MESSAGES_NOT_SUPPORTED.
*
* @return true if the protocol supports offline messages and
* false otherwise.
*/
public boolean isOfflineMessagingSupported()
{
return true;
}
/**
* Sends a WhiteboardObject to modify
* and modifies the local WhiteboardObject
*
* @param obj the WhiteboardObject to send and modify
* @throws OperationFailedException if sending
* the WhiteboardObject fails for some reason.
*/
public void moveWhiteboardObject(WhiteboardObject obj)
throws OperationFailedException
{
WhiteboardObject wbObj = updateWhiteboardObjects(obj);
if (wbObj != null)
sendWhiteboardObject(wbObj);
}
/**
* Sends a WhiteboardObject to delete
* and delete the local WhiteboardObject
*
* @param obj the WhiteboardObject to send and delete
* @throws OperationFailedException if sending
* the WhiteboardObject fails for some reason.
*/
public void deleteWhiteboardObject(WhiteboardObject obj)
throws OperationFailedException
{
Iterator participants = getWhiteboardParticipants();
if (!participants.hasNext())
return;
WhiteboardParticipantJabberImpl participant
= (WhiteboardParticipantJabberImpl) participants.next();
Contact contact = participant.getContact();
try
{
assertConnected();
org.jivesoftware.smack.packet.Message msg =
new org.jivesoftware.smack.packet.Message();
WhiteboardObjectPacketExtension messageJI =
new WhiteboardObjectPacketExtension(obj.getID(),
WhiteboardObjectPacketExtension.ACTION_DELETE);
msg.addExtension(messageJI);
msg.addExtension(new Version());
MessageEventManager.addNotificationsRequests(msg, true, false,
false, true);
smackChat.sendMessage(msg);
WhiteboardObjectDeliveredEvent msgDeliveredEvt =
new WhiteboardObjectDeliveredEvent(
this, obj, contact, new Date());
fireMessageEvent(msgDeliveredEvt);
int i = 0;
while (i < whiteboardObjects.size())
{
WhiteboardObjectJabberImpl wbObj =
(WhiteboardObjectJabberImpl) whiteboardObjects.get(i);
if (wbObj.getID().equals(obj.getID()))
whiteboardObjects.remove(i);
else
i++;
}
}
catch (XMPPException ex)
{
ex.printStackTrace();
logger.error("message not send", ex);
}
}
/**
* Sends the message to the destination indicated by the
* to contact.
* @param to the Contact to send message to
* @param message the Message to send.
* @throws java.lang.IllegalStateException if the underlying stack is
* not registered and initialized.
* @throws java.lang.IllegalArgumentException if to is not an
* instance of ContactImpl.
*/
public void sendWhiteboardObject(WhiteboardObject message)
throws OperationFailedException
{
Iterator participants = getWhiteboardParticipants();
if (!participants.hasNext())
return;
WhiteboardParticipantJabberImpl participant
= (WhiteboardParticipantJabberImpl) participants.next();
Contact contact = participant.getContact();
try
{
assertConnected();
org.jivesoftware.smack.packet.Message msg =
new org.jivesoftware.smack.packet.Message();
WhiteboardObjectPacketExtension messageJI =
new WhiteboardObjectPacketExtension(
(WhiteboardObjectJabberImpl) message,
WhiteboardObjectPacketExtension.ACTION_DRAW);
msg.addExtension(messageJI);
msg.addExtension(new Version());
MessageEventManager.addNotificationsRequests(msg, true, false,
false, true);
smackChat.sendMessage(msg);
WhiteboardObjectDeliveredEvent msgDeliveredEvt =
new WhiteboardObjectDeliveredEvent(
this, message, contact, new Date());
fireMessageEvent(msgDeliveredEvt);
}
catch (XMPPException ex)
{
ex.printStackTrace();
logger.error("message not send", ex);
}
}
/**
* Utility method throwing an exception if the stack is not properly
* initialized.
* @throws java.lang.IllegalStateException if the underlying stack is
* not registered and initialized.
*/
private void assertConnected() throws IllegalStateException
{
if (jabberProvider == null)
throw new IllegalStateException(
"The provider must be non-null and signed on the "
+ "service before being able to communicate.");
if (!jabberProvider.isRegistered())
throw new IllegalStateException(
"The provider must be signed on the service before "
+ "being able to communicate.");
}
/**
* Compares the specified object with this whiteboard and returns true if it
* the specified object is an instance of a Whiteboard object and if the
* extending telephony protocol considers the whiteboards represented by
* both objects to be the same.
*
* @param obj the whiteboard to compare this one with.
* @return true in case both objects are pertaining to the same whiteboard
* and false otherwise.
*/
public boolean equals(Object obj)
{
if (obj == null || !(obj instanceof WhiteboardSession))
return false;
if (obj == this
|| ((WhiteboardSession) obj).getWhiteboardID().equals(
getWhiteboardID()))
return true;
return false;
}
/**
* Returns a hash code value for this whiteboard.
*
* @return a hash code value for this whiteboard.
*/
public int hashCode()
{
return getWhiteboardID().hashCode();
}
/**
* Returns a string textually representing this Whiteboard.
*
* @return a string representation of the object.
*/
public String toString()
{
return "Whiteboard: id=" + getWhiteboardID() + " participants="
+ getWhiteboardParticipantsCount();
}
/**
* Adds a whiteboard change listener to this whiteboard so that it could
* receive events on new whiteboard participants, theme changes and others.
*
* @param listener the listener to register
*/
public void addWhiteboardChangeListener(WhiteboardChangeListener listener)
{
synchronized (whiteboardListeners)
{
if (!whiteboardListeners.contains(listener))
this.whiteboardListeners.add(listener);
}
}
/**
* Removes listener to this whiteboard so that it won't receive
* further WhiteboardChangeEvents.
*
* @param listener the listener to register
*/
public void removeWhiteboardChangeListener(WhiteboardChangeListener listener)
{
synchronized (whiteboardListeners)
{
this.whiteboardListeners.remove(listener);
}
}
/**
* Returns a reference to the ProtocolProviderService instance
* that created this whiteboard.
*
* @return a reference to the ProtocolProviderService instance that
* created this whiteboard.
*/
public ProtocolProviderService getProtocolProvider()
{
return this.jabberProvider;
}
/**
* Creates a WhiteboardParticipantEvent with
* sourceWhiteboardParticipant and eventID and dispatches
* it on all currently registered listeners.
*
* @param sourceWhiteboardParticipant the source
* WhiteboardParticipant for the newly created event.
* @param eventID the ID of the event to create (see CPE member ints)
*/
public void fireWhiteboardParticipantEvent(
WhiteboardParticipant sourceWhiteboardParticipant, int eventID)
{
WhiteboardParticipantEvent cpEvent =
new WhiteboardParticipantEvent(this, sourceWhiteboardParticipant,
eventID);
logger.debug("Dispatching a WhiteboardParticipant event to "
+ whiteboardListeners.size() + " listeners. event is: "
+ cpEvent.toString());
Iterator listeners = null;
synchronized (whiteboardListeners)
{
listeners = new ArrayList(whiteboardListeners).iterator();
}
while (listeners.hasNext())
{
WhiteboardChangeListener listener =
(WhiteboardChangeListener) listeners.next();
if (eventID
== WhiteboardParticipantEvent
.WHITEBOARD_PARTICIPANT_ADDED)
{
listener.whiteboardParticipantAdded(cpEvent);
}
else if (eventID
== WhiteboardParticipantEvent
.WHITEBOARD_PARTICIPANT_REMOVED)
{
listener.whiteboardParticipantRemoved(cpEvent);
}
}
}
/**
* Creates a WhiteboardChangeEvent with this class as
* sourceWhiteboard, and the specified eventID and old
* and new values and dispatches it on all currently registered listeners.
*
* @param type the type of the event to create (see WhiteboardChangeEvent
* member ints)
* @param oldValue the value of the Whiteboard property that changed, before
* the event had occurred.
* @param newValue the value of the Whiteboard property that changed, after
* the event has occurred.
*/
public void fireWhiteboardChangeEvent(String type, Object oldValue,
Object newValue)
{
WhiteboardChangeEvent ccEvent =
new WhiteboardChangeEvent(this, type, oldValue, newValue);
logger.debug("Dispatching a WhiteboardChange event to "
+ whiteboardListeners.size() + " listeners. event is: "
+ ccEvent.toString());
Iterator listeners = null;
synchronized (whiteboardListeners)
{
listeners = new ArrayList(whiteboardListeners).iterator();
}
while (listeners.hasNext())
{
WhiteboardChangeListener listener =
(WhiteboardChangeListener) listeners.next();
if (type.equals(WhiteboardChangeEvent.WHITEBOARD_STATE_CHANGE))
listener.whiteboardStateChanged(ccEvent);
}
}
/**
* Returns the WhiteboardObjects in this whiteboard session.
* @return an Vector of WhiteboardObjects associated
* with this whiteboard.
*/
public Vector getWhiteboardObjects()
{
return whiteboardObjects;
}
/**
* Sets the state of this whiteboard
*
* @param newState a reference to the WhiteboardState instance that
* the whiteboard is to enter.
*/
public void setState(WhiteboardSessionState newState)
{
this.whiteboardState = newState;
}
/**
* Returns the state that this whiteboard is currently in.
*
* @return a reference to the WhiteboardState instance
* that the whiteboard is currently in.
*/
public WhiteboardSessionState getState()
{
return this.whiteboardState;
}
/**
* Delivers the specified event to all registered message listeners.
* @param evt the EventObject that we'd like delivered to all
* registered message listeners.
*/
public void fireMessageEvent(EventObject evt)
{
logger.debug("Dispatching a WhiteboardMessageEvent event to "
+ messageListeners.size() + " listeners. event is: "
+ evt.toString());
Iterator listeners = null;
synchronized (messageListeners)
{
listeners = new ArrayList(messageListeners).iterator();
}
while (listeners.hasNext())
{
WhiteboardObjectListener listener =
(WhiteboardObjectListener) listeners.next();
if (evt instanceof WhiteboardObjectDeliveredEvent)
{
listener.whiteboardObjectDelivered(
(WhiteboardObjectDeliveredEvent) evt);
}
else if (evt instanceof WhiteboardObjectReceivedEvent)
{
WhiteboardObjectJabberImpl wbObj =
(WhiteboardObjectJabberImpl) (
(WhiteboardObjectReceivedEvent) evt)
.getSourceWhiteboardObject();
listener.whiteboardObjectReceived(
(WhiteboardObjectReceivedEvent) evt);
whiteboardObjects.add(wbObj);
}
else if (evt instanceof WhiteboardObjectDeletedEvent)
{
String wbObjID = ((WhiteboardObjectDeletedEvent) evt).getId();
listener
.whiteboardObjectDeleted((WhiteboardObjectDeletedEvent) evt);
int i = 0;
while (i < whiteboardObjects.size())
{
WhiteboardObjectJabberImpl wbObj
= (WhiteboardObjectJabberImpl) whiteboardObjects.get(i);
if (wbObj.getID().equals(wbObjID))
whiteboardObjects.remove(i);
else
i++;
}
}
else if (evt instanceof WhiteboardObjectModifiedEvent)
{
WhiteboardObjectJabberImpl wbObj
= (WhiteboardObjectJabberImpl)
((WhiteboardObjectReceivedEvent) evt)
.getSourceWhiteboardObject();
listener.whiteboardObjecModified(
(WhiteboardObjectModifiedEvent) evt);
whiteboardObjects.remove(wbObj);//remove the old id object
whiteboardObjects.add(wbObj); //add the new object for this id
}
else if (evt instanceof WhiteboardObjectDeliveryFailedEvent)
{
listener.whiteboardObjectDeliveryFailed(
(WhiteboardObjectDeliveryFailedEvent) evt);
}
}
}
private WhiteboardObject updateWhiteboardObjects(WhiteboardObject ws)
{
WhiteboardObjectJabberImpl wbObj = null;
int i = 0;
while (i < whiteboardObjects.size())
{
WhiteboardObjectJabberImpl wbObjTmp =
(WhiteboardObjectJabberImpl) whiteboardObjects.get(i);
if (wbObjTmp.getID().equals(ws.getID()))
{
wbObj = wbObjTmp;
break;
}
else
i++;
}
if (wbObj == null)
return null;
if (ws instanceof WhiteboardObjectPath)
{
WhiteboardObjectPathJabberImpl obj =
(WhiteboardObjectPathJabberImpl) wbObj;
obj.setPoints(((WhiteboardObjectPath) ws).getPoints());
obj.setColor(ws.getColor());
obj.setThickness(ws.getThickness());
}
else if (ws instanceof WhiteboardObjectPolyLine)
{
WhiteboardObjectPolyLineJabberImpl obj =
(WhiteboardObjectPolyLineJabberImpl) wbObj;
obj.setPoints(((WhiteboardObjectPolyLine) ws).getPoints());
obj.setColor(ws.getColor());
obj.setThickness(ws.getThickness());
}
else if (ws instanceof WhiteboardObjectPolygon)
{
WhiteboardObjectPolygonJabberImpl obj =
(WhiteboardObjectPolygonJabberImpl) wbObj;
obj.setPoints(((WhiteboardObjectPolygon) ws).getPoints());
obj.setBackgroundColor(((WhiteboardObjectPolygon) ws)
.getBackgroundColor());
obj.setFill(((WhiteboardObjectPolygon) ws).isFill());
obj.setColor(ws.getColor());
obj.setThickness(ws.getThickness());
}
else if (ws instanceof WhiteboardObjectLine)
{
WhiteboardObjectLineJabberImpl obj =
(WhiteboardObjectLineJabberImpl) wbObj;
obj.setWhiteboardPointStart(((WhiteboardObjectLine) ws)
.getWhiteboardPointStart());
obj.setWhiteboardPointEnd(((WhiteboardObjectLine) ws)
.getWhiteboardPointEnd());
obj.setColor(ws.getColor());
obj.setThickness(ws.getThickness());
}
else if (ws instanceof WhiteboardObjectRect)
{
WhiteboardObjectRectJabberImpl obj =
(WhiteboardObjectRectJabberImpl) wbObj;
obj.setFill(((WhiteboardObjectRect) ws).isFill());
obj.setHeight(((WhiteboardObjectRect) ws).getHeight());
obj.setWhiteboardPoint(((WhiteboardObjectRect) ws)
.getWhiteboardPoint());
obj.setWidth((((WhiteboardObjectRect) ws)).getWidth());
obj.setColor(ws.getColor());
obj.setThickness(ws.getThickness());
}
else if (ws instanceof WhiteboardObjectCircle)
{
WhiteboardObjectCircleJabberImpl obj =
(WhiteboardObjectCircleJabberImpl) wbObj;
obj.setFill(((WhiteboardObjectCircle) ws).isFill());
obj.setRadius(((WhiteboardObjectCircle) ws).getRadius());
obj.setWhiteboardPoint(((WhiteboardObjectCircle) ws)
.getWhiteboardPoint());
obj.setBackgroundColor((((WhiteboardObjectCircle) ws))
.getBackgroundColor());
obj.setColor(ws.getColor());
obj.setThickness(ws.getThickness());
}
else if (ws instanceof WhiteboardObjectText)
{
WhiteboardObjectTextJabberImpl obj =
(WhiteboardObjectTextJabberImpl) wbObj;
obj.setFontName(((WhiteboardObjectText) ws).getFontName());
obj.setFontSize(((WhiteboardObjectText) ws).getFontSize());
obj.setText(((WhiteboardObjectText) ws).getText());
obj.setWhiteboardPoint(((WhiteboardObjectText) ws)
.getWhiteboardPoint());
obj.setColor(ws.getColor());
obj.setThickness(ws.getThickness());
}
else if (ws instanceof WhiteboardObjectImage)
{
WhiteboardObjectImageJabberImpl obj =
(WhiteboardObjectImageJabberImpl) wbObj;
obj.setBackgroundImage(((WhiteboardObjectImage) ws)
.getBackgroundImage());
obj.setHeight(((WhiteboardObjectImage) ws).getHeight());
obj.setWhiteboardPoint(((WhiteboardObjectImage) ws)
.getWhiteboardPoint());
obj.setWidth(((WhiteboardObjectImage) ws).getWidth());
obj.setColor(ws.getColor());
obj.setThickness(ws.getThickness());
}
whiteboardObjects.set(i, wbObj);
return wbObj;
}
/**
* Returns all the type of WhiteboardObject that this whiteboard support.
*
* @return all the WhiteboardObject supported by this WhiteboardSession.
*/
public String[] getSupportedWhiteboardObjects()
{
String[] type = new String[8];
type[0] = WhiteboardObjectPath.NAME;
type[1] = WhiteboardObjectPolyLine.NAME;
type[2] = WhiteboardObjectPolygon.NAME;
type[3] = WhiteboardObjectLine.NAME;
type[4] = WhiteboardObjectRect.NAME;
type[5] = WhiteboardObjectCircle.NAME;
type[6] = WhiteboardObjectText.NAME;
type[7] = WhiteboardObjectImage.NAME;
return type;
}
/**
* Listens for white-board messages and fires the appropriate events to
* notify all interested listeners.
*/
private class WhiteboardSmackMessageListener
implements PacketListener
{
public void processPacket(Packet packet)
{
if (!(packet instanceof org.jivesoftware.smack.packet.Message))
return;
PacketExtension objectExt =
packet.getExtension(
WhiteboardObjectPacketExtension.ELEMENT_NAME,
WhiteboardObjectPacketExtension.NAMESPACE);
PacketExtension sessionExt =
packet.getExtension(
WhiteboardSessionPacketExtension.ELEMENT_NAME,
WhiteboardSessionPacketExtension.NAMESPACE);
org.jivesoftware.smack.packet.Message msg =
(org.jivesoftware.smack.packet.Message) packet;
if (sessionExt != null)
{
WhiteboardSessionPacketExtension sessionMessage
= (WhiteboardSessionPacketExtension) sessionExt;
if (sessionMessage.getAction().equals(
WhiteboardSessionPacketExtension.ACTION_LEAVE))
{
fireWhiteboardParticipantEvent(
findWhiteboardParticipantFromContactAddress(
sessionMessage.getContactAddress()),
WhiteboardParticipantEvent
.WHITEBOARD_PARTICIPANT_REMOVED);
}
}
if (objectExt == null)
return;
String fromUserID = StringUtils.parseBareAddress(msg.getFrom());
if (logger.isDebugEnabled())
{
logger.debug("Received from " + fromUserID + " the message "
+ msg.toXML());
}
OperationSetPersistentPresenceJabberImpl presenceOpSet
= (OperationSetPersistentPresenceJabberImpl) jabberProvider
.getOperationSet(OperationSetPresence.class);
// If there's no presence operation set we return, because there's
// not contact to associate the event with.
if (presenceOpSet == null)
return;
Contact sourceContact
= presenceOpSet.findContactByID(fromUserID);
// If the sender is not our contact we don't care of this message
if (!wbParticipants.containsKey(sourceContact.getAddress()))
return;
WhiteboardObjectPacketExtension newMessage
= (WhiteboardObjectPacketExtension) objectExt;
if (msg.getType()
== org.jivesoftware.smack.packet.Message.Type.error)
{
logger.info("WBObject error received from " + fromUserID);
int errorCode = packet.getError().getCode();
int errorResultCode =
WhiteboardObjectDeliveryFailedEvent.UNKNOWN_ERROR;
if (errorCode == 503)
{
org.jivesoftware.smackx.packet.MessageEvent msgEvent =
(org.jivesoftware.smackx.packet.MessageEvent) packet
.getExtension("x", "jabber:x:event");
if (msgEvent != null && msgEvent.isOffline())
{
errorResultCode
= WhiteboardObjectDeliveryFailedEvent
.OFFLINE_MESSAGES_NOT_SUPPORTED;
}
}
WhiteboardObjectDeliveryFailedEvent evt =
new WhiteboardObjectDeliveryFailedEvent(
WhiteboardSessionJabberImpl.this,
newMessage.getWhiteboardObject(),
sourceContact,
errorResultCode,
new Date());
fireMessageEvent(evt);
return;
}
if (newMessage.getAction().equals(
WhiteboardObjectPacketExtension.ACTION_DELETE))
{
WhiteboardObjectDeletedEvent msgDeletedEvt
= new WhiteboardObjectDeletedEvent(
WhiteboardSessionJabberImpl.this,
newMessage.getWhiteboardObjectID(),
sourceContact,
new Date());
fireMessageEvent(msgDeletedEvt);
}
else if (newMessage.getAction().equals(
WhiteboardObjectPacketExtension.ACTION_DRAW))
{
WhiteboardObjectReceivedEvent msgReceivedEvt
= new WhiteboardObjectReceivedEvent(
WhiteboardSessionJabberImpl.this,
newMessage.getWhiteboardObject(),
sourceContact,
new Date());
fireMessageEvent(msgReceivedEvt);
}
}
}
/**
* Checks if the participant given by participantName is contained
* in this white-board session.
*
* @param participantName the name of the participant to search for
* @return true
if a participant with the given name is
* contained in this session, false
- otherwise
*/
public boolean isParticipantContained(String participantName)
{
if (wbParticipants.containsKey(participantName))
return true;
return false;
}
/**
* Searches all participants contained in this white board and returns the
* one that corresponds to the given contact address.
*
* @param contactAddress the address of the contact to search for.
* @return the WhiteboardParticipant, contained in this
* white board session and corresponding to the given contact address
*/
private WhiteboardParticipant findWhiteboardParticipantFromContactAddress(
String contactAddress)
{
Enumeration participants = wbParticipants.elements();
while(participants.hasMoreElements())
{
WhiteboardParticipant participant
= (WhiteboardParticipant) participants.nextElement();
if (participant.getContactAddress().equals(contactAddress))
return participant;
}
return null;
}
}