/**************************************************************************** * Copyright (c) 2004 Composent, Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Composent, Inc. - initial API and implementation *****************************************************************************/ package org.eclipse.ecf.internal.provider.xmpp; import java.net.URISyntaxException; import java.util.*; import org.eclipse.core.runtime.IAdapterManager; import org.eclipse.ecf.core.identity.ID; import org.eclipse.ecf.core.identity.Namespace; import org.eclipse.ecf.core.sharedobject.*; import org.eclipse.ecf.core.user.User; import org.eclipse.ecf.core.util.Event; import org.eclipse.ecf.internal.provider.xmpp.events.*; import org.eclipse.ecf.presence.IIMMessageListener; import org.eclipse.ecf.presence.IPresence; import org.eclipse.ecf.presence.chatroom.*; import org.eclipse.ecf.provider.xmpp.identity.XMPPID; import org.eclipse.ecf.provider.xmpp.identity.XMPPRoomID; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.packet.Presence.Mode; import org.jivesoftware.smack.packet.Presence.Type; public class XMPPChatRoomContainerHelper implements ISharedObject { ISharedObjectConfig config = null; private final List messageListeners = new ArrayList(); private Namespace usernamespace = null; private XMPPConnection connection = null; private final List participantListeners = new ArrayList(); private ID roomID = null; private final List chatRoomContainerParticipants = Collections .synchronizedList(new ArrayList()); protected void trace(String message) { } protected void addChatParticipantListener( IChatRoomParticipantListener listener) { synchronized (participantListeners) { participantListeners.add(listener); } } protected void removeChatParticipantListener( IChatRoomParticipantListener listener) { synchronized (participantListeners) { participantListeners.remove(listener); } } public XMPPChatRoomContainerHelper(Namespace usernamespace, XMPPConnection conn) { super(); this.usernamespace = usernamespace; this.connection = conn; } protected ISharedObjectContext getContext() { return config.getContext(); } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.ISharedObject#init(org.eclipse.ecf.core.ISharedObjectConfig) */ public void init(ISharedObjectConfig initData) throws SharedObjectInitException { this.config = initData; } protected ID createUserIDFromName(String name) { ID result = null; try { result = new XMPPID(usernamespace, name); return result; } catch (final Exception e) { return null; } } protected Message.Type[] ALLOWED_MESSAGES = { Message.Type.groupchat }; protected Message filterMessageType(Message msg) { for (int i = 0; i < ALLOWED_MESSAGES.length; i++) { if (ALLOWED_MESSAGES[i].equals(msg.getType())) { return msg; } } return null; } protected String canonicalizeRoomFrom(String from) { if (from == null) return null; final int atIndex = from.indexOf('@'); String hostname = null; String username = null; final int index = from.indexOf("/"); if (atIndex > 0 && index > 0) { hostname = from.substring(atIndex + 1, index); username = from.substring(index + 1); return username + "@" + hostname; } return from; } protected void fireMessageListeners(ID from, String body) { List toNotify = null; synchronized (messageListeners) { toNotify = new ArrayList(messageListeners); } for (final Iterator i = toNotify.iterator(); i.hasNext();) { final IIMMessageListener l = (IIMMessageListener) i.next(); l.handleMessageEvent(new ChatRoomMessageEvent(from, new ChatRoomMessage(from, roomID, body))); } } protected String canonicalizeRoomTo(String to) { if (to == null) return null; final int index = to.indexOf("/"); if (index > 0) { return to.substring(0, index); } else return to; } protected ID createRoomIDFromName(String from) { try { return new XMPPRoomID(usernamespace, connection, from); } catch (final URISyntaxException e) { return null; } } protected void handleMessageEvent(MessageEvent evt) { final Message msg = filterMessageType(evt.getMessage()); if (msg != null) fireMessageListeners(createUserIDFromName(canonicalizeRoomFrom(msg .getFrom())), msg.getBody()); } protected IPresence.Type createIPresenceType(Presence xmppPresence) { if (xmppPresence == null) return IPresence.Type.AVAILABLE; final Type type = xmppPresence.getType(); if (type == Presence.Type.available) { return IPresence.Type.AVAILABLE; } else if (type == Presence.Type.error) { return IPresence.Type.ERROR; } else if (type == Presence.Type.subscribe) { return IPresence.Type.SUBSCRIBE; } else if (type == Presence.Type.subscribed) { return IPresence.Type.SUBSCRIBED; } else if (type == Presence.Type.unsubscribe) { return IPresence.Type.UNSUBSCRIBE; } else if (type == Presence.Type.unsubscribed) { return IPresence.Type.UNSUBSCRIBED; } else if (type == Presence.Type.unavailable) { return IPresence.Type.UNAVAILABLE; } return IPresence.Type.AVAILABLE; } protected IPresence.Mode createIPresenceMode(Presence xmppPresence) { if (xmppPresence == null) return IPresence.Mode.AVAILABLE; final Mode mode = xmppPresence.getMode(); if (mode == Presence.Mode.available) { return IPresence.Mode.AVAILABLE; } else if (mode == Presence.Mode.away) { return IPresence.Mode.AWAY; } else if (mode == Presence.Mode.chat) { return IPresence.Mode.CHAT; } else if (mode == Presence.Mode.dnd) { return IPresence.Mode.DND; } else if (mode == Presence.Mode.xa) { return IPresence.Mode.EXTENDED_AWAY; } /*else if (mode == Presence.Mode.invisible) { return IPresence.Mode.INVISIBLE; }*/ return IPresence.Mode.AVAILABLE; } protected IPresence createIPresence(Presence xmppPresence) { final String status = xmppPresence.getStatus(); final IPresence newPresence = new org.eclipse.ecf.presence.Presence( createIPresenceType(xmppPresence), status, createIPresenceMode(xmppPresence)); return newPresence; } protected void disconnect() { chatRoomContainerParticipants.clear(); setRoomID(null); } protected void handlePresenceEvent(PresenceEvent evt) { final Presence xmppPresence = evt.getPresence(); final String from = canonicalizeRoomFrom(xmppPresence.getFrom()); final IPresence newPresence = createIPresence(xmppPresence); final ID fromID = createUserIDFromName(from); if (newPresence.getType().equals(IPresence.Type.AVAILABLE)) { if (!chatRoomContainerParticipants.contains(fromID)) chatRoomContainerParticipants.add(fromID); } else chatRoomContainerParticipants.remove(fromID); fireParticipant(fromID, newPresence); } protected void handleChatMembershipEvent(ChatMembershipEvent evt) { final String from = canonicalizeRoomFrom(evt.getFrom()); final ID fromID = createUserIDFromName(from); fireChatParticipant(fromID, evt.isAdd()); } protected void fireParticipant(ID fromID, IPresence presence) { List toNotify = null; synchronized (participantListeners) { toNotify = new ArrayList(participantListeners); } for (final Iterator i = toNotify.iterator(); i.hasNext();) { final IChatRoomParticipantListener l = (IChatRoomParticipantListener) i .next(); l.handlePresenceUpdated(fromID, presence); } } protected void fireChatParticipant(ID fromID, boolean join) { List toNotify = null; synchronized (participantListeners) { toNotify = new ArrayList(participantListeners); } for (final Iterator i = toNotify.iterator(); i.hasNext();) { final IChatRoomParticipantListener l = (IChatRoomParticipantListener) i .next(); if (join) { l.handleArrived(new User(fromID)); } else { l.handleDeparted(new User(fromID)); } } } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.ISharedObject#handleEvent(org.eclipse.ecf.core.util.Event) */ public void handleEvent(Event event) { trace("handleEvent(" + event + ")"); if (event instanceof MessageEvent) { handleMessageEvent((MessageEvent) event); } else if (event instanceof PresenceEvent) { handlePresenceEvent((PresenceEvent) event); } else if (event instanceof ChatMembershipEvent) { handleChatMembershipEvent((ChatMembershipEvent) event); } else trace("unrecognized event " + event); } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.ISharedObject#handleEvents(org.eclipse.ecf.core.util.Event[]) */ public void handleEvents(Event[] events) { for (int i = 0; i < events.length; i++) { this.handleEvent(events[i]); } } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.ISharedObject#dispose(org.eclipse.ecf.core.identity.ID) */ public void dispose(ID containerID) { synchronized (messageListeners) { messageListeners.clear(); } synchronized (participantListeners) { participantListeners.clear(); } synchronized (chatRoomContainerParticipants) { chatRoomContainerParticipants.clear(); } this.config = null; this.connection = null; this.usernamespace = null; } /* * (non-Javadoc) * * @see org.eclipse.ecf.core.ISharedObject#getAdapter(java.lang.Class) */ public Object getAdapter(Class adapter) { if (adapter == null) return null; if (adapter.isInstance(this)) return this; final IAdapterManager adapterManager = XmppPlugin.getDefault() .getAdapterManager(); return (adapterManager == null) ? null : adapterManager.loadAdapter( this, adapter.getName()); } /** * @param msgListener */ protected void addChatRoomMessageListener(IIMMessageListener msgListener) { synchronized (messageListeners) { messageListeners.add(msgListener); } } /** * @param msgListener */ public void removeChatRoomMessageListener(IIMMessageListener msgListener) { synchronized (messageListeners) { messageListeners.remove(msgListener); } } /** * @param remoteServerID */ protected void setRoomID(ID roomID) { this.roomID = roomID; } /** * @return array of IDs of chat room participants. */ public ID[] getChatRoomParticipants() { return (ID[]) chatRoomContainerParticipants.toArray(new ID[] {}); } }