| /******************************************************************************* |
| * 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.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.WeakHashMap; |
| |
| import org.eclipse.core.runtime.IAdapterManager; |
| import org.eclipse.ecf.core.identity.ID; |
| import org.eclipse.ecf.core.identity.IDFactory; |
| import org.eclipse.ecf.core.sharedobject.ISharedObject; |
| import org.eclipse.ecf.core.sharedobject.ISharedObjectConfig; |
| import org.eclipse.ecf.core.sharedobject.ISharedObjectContext; |
| import org.eclipse.ecf.core.sharedobject.SharedObjectInitException; |
| import org.eclipse.ecf.core.sharedobject.events.ISharedObjectActivatedEvent; |
| import org.eclipse.ecf.core.sharedobject.events.ISharedObjectMessageEvent; |
| import org.eclipse.ecf.core.sharedobject.events.ISharedObjectMessageListener; |
| import org.eclipse.ecf.core.user.IUser; |
| import org.eclipse.ecf.core.user.User; |
| import org.eclipse.ecf.core.util.AsyncResult; |
| import org.eclipse.ecf.core.util.ECFException; |
| import org.eclipse.ecf.core.util.Event; |
| import org.eclipse.ecf.core.util.IAsyncResult; |
| import org.eclipse.ecf.core.util.ICallable; |
| import org.eclipse.ecf.internal.provider.xmpp.events.IQEvent; |
| import org.eclipse.ecf.internal.provider.xmpp.events.MessageEvent; |
| import org.eclipse.ecf.internal.provider.xmpp.events.PresenceEvent; |
| import org.eclipse.ecf.internal.provider.xmpp.smack.ECFConnection; |
| import org.eclipse.ecf.presence.IPresence; |
| import org.eclipse.ecf.presence.IPresenceListener; |
| import org.eclipse.ecf.presence.IPresenceSender; |
| import org.eclipse.ecf.presence.im.IChatManager; |
| import org.eclipse.ecf.presence.im.ITypingMessage; |
| import org.eclipse.ecf.presence.im.TypingMessage; |
| import org.eclipse.ecf.presence.roster.AbstractRosterManager; |
| import org.eclipse.ecf.presence.roster.IRosterEntry; |
| import org.eclipse.ecf.presence.roster.IRosterGroup; |
| import org.eclipse.ecf.presence.roster.IRosterItem; |
| import org.eclipse.ecf.presence.roster.IRosterManager; |
| import org.eclipse.ecf.presence.roster.IRosterSubscriptionSender; |
| import org.eclipse.ecf.provider.xmpp.XMPPContainer; |
| import org.eclipse.ecf.provider.xmpp.identity.XMPPID; |
| import org.eclipse.ecf.provider.xmpp.identity.XMPPRoomID; |
| import org.jivesoftware.smack.Roster; |
| import org.jivesoftware.smack.RosterEntry; |
| import org.jivesoftware.smack.RosterGroup; |
| import org.jivesoftware.smack.XMPPException; |
| import org.jivesoftware.smack.packet.IQ; |
| import org.jivesoftware.smack.packet.Message; |
| import org.jivesoftware.smack.packet.Presence; |
| import org.jivesoftware.smack.packet.RosterPacket; |
| import org.jivesoftware.smack.packet.Presence.Mode; |
| import org.jivesoftware.smack.packet.Presence.Type; |
| import org.jivesoftware.smackx.packet.VCard; |
| |
| public class XMPPContainerPresenceHelper implements ISharedObject { |
| |
| public static final String VCARD = "vcard"; |
| public static final String VCARD_EMAIL = VCARD + ".email"; |
| public static final String VCARD_EMAIL_HOME = VCARD_EMAIL + ".home"; |
| public static final String VCARD_EMAIL_WORK = VCARD_EMAIL + ".work"; |
| public static final String VCARD_NAME = VCARD + ".name"; |
| public static final String VCARD_NAME_FIRST = VCARD_NAME + ".first"; |
| public static final String VCARD_NAME_MIDDLE = VCARD_NAME + ".middle"; |
| public static final String VCARD_NAME_LAST = VCARD_NAME + ".last"; |
| public static final String VCARD_NAME_NICK = VCARD_NAME + ".nick"; |
| public static final String VCARD_PHONE = VCARD + ".phone"; |
| public static final String VCARD_PHONE_HOME = VCARD_PHONE + ".home"; |
| public static final String VCARD_PHONE_HOME_VOICE = VCARD_PHONE_HOME + ".voice"; |
| public static final String VCARD_PHONE_HOME_CELL = VCARD_PHONE_HOME + ".cell"; |
| public static final String VCARD_PHONE_WORK = VCARD_PHONE + ".work"; |
| public static final String VCARD_PHONE_WORK_VOICE = VCARD_PHONE_WORK + ".voice"; |
| public static final String VCARD_PHONE_WORK_CELL = VCARD_PHONE_WORK + ".cell"; |
| |
| private ISharedObjectConfig config = null; |
| |
| private final List sharedObjectMessageListeners = new ArrayList(); |
| |
| private XMPPContainer container = null; |
| |
| private XMPPChatManager chatManager = null; |
| |
| private final List presenceListeners = new ArrayList(); |
| |
| public XMPPContainerPresenceHelper(XMPPContainer container) { |
| this.container = container; |
| chatManager = new XMPPChatManager(this); |
| roster = new org.eclipse.ecf.presence.roster.Roster(container); |
| rosterManager = new PresenceRosterManager(roster); |
| } |
| |
| // ISharedObject implementation |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ecf.core.ISharedObject#init(org.eclipse.ecf.core.ISharedObjectConfig) |
| */ |
| public void init(ISharedObjectConfig initData) throws SharedObjectInitException { |
| this.config = initData; |
| } |
| |
| /* |
| * (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 ISharedObjectActivatedEvent) { |
| } else if (event instanceof IQEvent) { |
| handleIQEvent((IQEvent) event); |
| } else if (event instanceof MessageEvent) { |
| handleMessageEvent((MessageEvent) event); |
| } else if (event instanceof PresenceEvent) { |
| handlePresenceEvent((PresenceEvent) event); |
| } else if (event instanceof ISharedObjectMessageEvent) { |
| handleSharedObjectMessageEvent((ISharedObjectMessageEvent) event); |
| } else { |
| trace("unhandled 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++) { |
| handleEvent(events[i]); |
| } |
| } |
| |
| public void disconnect() { |
| rosterManager.disconnect(); |
| chatManager.disconnect(); |
| synchronized (sharedObjectMessageListeners) { |
| sharedObjectMessageListeners.clear(); |
| } |
| synchronized (presenceListeners) { |
| presenceListeners.clear(); |
| } |
| vcardCache.clear(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ecf.core.ISharedObject#dispose(org.eclipse.ecf.core.identity.ID) |
| */ |
| public void dispose(ID containerID) { |
| vcardCache.clear(); |
| } |
| |
| /* |
| * (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()); |
| } |
| |
| // end ISharedObject implementation |
| |
| protected org.eclipse.ecf.presence.roster.Roster roster; |
| |
| protected PresenceRosterManager rosterManager; |
| |
| class PresenceRosterManager extends AbstractRosterManager { |
| |
| public PresenceRosterManager(org.eclipse.ecf.presence.roster.Roster roster) { |
| super(roster); |
| } |
| |
| public void notifySubscriptionListener(ID fromID, IPresence presence) { |
| this.fireSubscriptionListener(fromID, presence.getType()); |
| } |
| |
| public void notifyRosterUpdate(IRosterItem changedItem) { |
| fireRosterUpdate(changedItem); |
| } |
| |
| public void notifyRosterAdd(IRosterEntry entry) { |
| fireRosterAdd(entry); |
| } |
| |
| public void notifyRosterRemove(IRosterEntry entry) { |
| fireRosterRemove(entry); |
| } |
| |
| public void disconnect() { |
| getRoster().getItems().clear(); |
| super.disconnect(); |
| fireRosterUpdate(roster); |
| } |
| |
| public void setUser(IUser user) { |
| final org.eclipse.ecf.presence.roster.Roster roster = (org.eclipse.ecf.presence.roster.Roster) getRoster(); |
| roster.setUser(user); |
| notifyRosterUpdate(roster); |
| } |
| |
| org.eclipse.ecf.presence.IPresenceSender rosterPresenceSender = new org.eclipse.ecf.presence.IPresenceSender() { |
| public void sendPresenceUpdate(ID toID, org.eclipse.ecf.presence.IPresence presence) throws ECFException { |
| try { |
| getConnectionOrThrowIfNull().sendPresenceUpdate(toID, createPresence(presence)); |
| } catch (final IOException e) { |
| traceAndThrowECFException("sendPresenceUpdate", e); |
| } |
| } |
| |
| }; |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ecf.presence.roster.AbstractRosterManager#getPresenceSender() |
| */ |
| public IPresenceSender getPresenceSender() { |
| return rosterPresenceSender; |
| } |
| |
| org.eclipse.ecf.presence.roster.IRosterSubscriptionSender rosterSubscriptionSender = new org.eclipse.ecf.presence.roster.IRosterSubscriptionSender() { |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ecf.presence.roster.IRosterSubscriptionSender#sendRosterAdd(java.lang.String, |
| * java.lang.String, java.lang.String[]) |
| */ |
| public void sendRosterAdd(String user, String name, String[] groups) throws ECFException { |
| try { |
| getConnectionOrThrowIfNull().sendRosterAdd(user, name, groups); |
| } catch (final Exception e) { |
| traceAndThrowECFException("sendRosterAdd", e); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ecf.presence.roster.IRosterSubscriptionSender#sendRosterRemove(org.eclipse.ecf.core.identity.ID) |
| */ |
| public void sendRosterRemove(ID userID) throws ECFException { |
| try { |
| if (!(userID instanceof XMPPID)) |
| throw new ECFException("invalid userID"); |
| final XMPPID xmppID = (XMPPID) userID; |
| getConnectionOrThrowIfNull().sendRosterRemove(xmppID.getUsernameAtHost()); |
| } catch (final Exception e) { |
| traceAndThrowECFException("sendRosterRemove", e); |
| } |
| } |
| |
| }; |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ecf.presence.roster.AbstractRosterManager#getRosterSubscriptionSender() |
| */ |
| public IRosterSubscriptionSender getRosterSubscriptionSender() { |
| return rosterSubscriptionSender; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ecf.presence.roster.IRosterManager#addPresenceListener(org.eclipse.ecf.presence.roster.IPresenceListener) |
| */ |
| public void addPresenceListener(IPresenceListener listener) { |
| synchronized (presenceListeners) { |
| presenceListeners.add(listener); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ecf.presence.roster.IRosterManager#removePresenceListener(org.eclipse.ecf.presence.roster.IPresenceListener) |
| */ |
| public void removePresenceListener(IPresenceListener listener) { |
| synchronized (presenceListeners) { |
| presenceListeners.add(listener); |
| } |
| } |
| |
| } |
| |
| /** |
| * @return IRosterManager roster manager. Will not return <code>null</code>. |
| */ |
| public IRosterManager getRosterManager() { |
| return rosterManager; |
| } |
| |
| /** |
| * @param user |
| * set the user for this presence helper. |
| */ |
| public void setUser(IUser user) { |
| rosterManager.setUser(user); |
| } |
| |
| protected void addSharedObjectMessageListener(ISharedObjectMessageListener listener) { |
| synchronized (sharedObjectMessageListeners) { |
| sharedObjectMessageListeners.add(listener); |
| } |
| } |
| |
| protected void sendTypingMessage(ID toID, boolean isTyping, String body) throws IOException { |
| getContext().sendMessage(toID, new TypingMessage(rosterManager.getRoster().getUser().getID(), isTyping, body)); |
| } |
| |
| protected void handleSharedObjectMessageEvent(ISharedObjectMessageEvent event) { |
| List toNotify = null; |
| synchronized (sharedObjectMessageListeners) { |
| toNotify = new ArrayList(sharedObjectMessageListeners); |
| } |
| for (final Iterator i = toNotify.iterator(); i.hasNext();) { |
| final ISharedObjectMessageListener l = (ISharedObjectMessageListener) i.next(); |
| l.handleSharedObjectMessage(event); |
| } |
| |
| final Object data = event.getData(); |
| if (data instanceof ITypingMessage) { |
| final ITypingMessage tmess = (ITypingMessage) data; |
| chatManager.fireTypingMessage(tmess.getFromID(), tmess); |
| } |
| |
| } |
| |
| protected void removeSharedObjectMessageListener(ISharedObjectMessageListener listener) { |
| synchronized (sharedObjectMessageListeners) { |
| sharedObjectMessageListeners.remove(listener); |
| } |
| } |
| |
| private void addToRoster(IRosterItem[] items) { |
| for (int i = 0; i < items.length; i++) { |
| roster.addItem(items[i]); |
| } |
| rosterManager.notifyRosterUpdate(roster); |
| } |
| |
| protected ISharedObjectContext getContext() { |
| return config.getContext(); |
| } |
| |
| protected String getUserNameFromXMPPAddress(XMPPID userID) { |
| return userID.getUsername(); |
| } |
| |
| protected IRosterEntry createRosterEntry(RosterEntry entry) { |
| return createRosterEntry(createIDFromName(entry.getUser()), entry.getName(), entry.getGroups()); |
| } |
| |
| protected IRosterEntry createRosterEntry(RosterPacket.Item entry) { |
| return createRosterEntry(createIDFromName(entry.getUser()), entry.getName(), entry.getGroupNames()); |
| } |
| |
| protected void handleIQEvent(IQEvent evt) { |
| final IQ iq = evt.getIQ(); |
| if (iq instanceof RosterPacket) { |
| // Roster packet...report to UI |
| final RosterPacket rosterPacket = (RosterPacket) iq; |
| if (rosterPacket.getType() == IQ.Type.SET || rosterPacket.getType() == IQ.Type.RESULT) { |
| for (final Iterator i = rosterPacket.getRosterItems(); i.hasNext();) { |
| final RosterPacket.Item item = (RosterPacket.Item) i.next(); |
| final RosterPacket.ItemType itemType = item.getItemType(); |
| boolean remove = false; |
| final IRosterItem items[] = createRosterEntries(item); |
| final IRosterEntry entry = createRosterEntry(item); |
| if (itemType == RosterPacket.ItemType.NONE || itemType == RosterPacket.ItemType.REMOVE) { |
| removeItemFromRoster(roster.getItems(), createIDFromName(item.getUser())); |
| remove = true; |
| } else { |
| remove = false; |
| addToRoster(items); |
| } |
| // In both cases fire set roster entry |
| fireSetRosterEntry(remove, entry); |
| } |
| } |
| } else { |
| trace("Received non rosterpacket IQ message"); |
| } |
| } |
| |
| protected void fireSetRosterEntry(boolean remove, IRosterEntry entry) { |
| if (remove) |
| rosterManager.notifyRosterRemove(entry); |
| else |
| rosterManager.notifyRosterAdd(entry); |
| } |
| |
| private void removeItemFromRoster(Collection rosterItems, XMPPID itemIDToRemove) { |
| boolean removed = false; |
| synchronized (rosterItems) { |
| for (final Iterator i = rosterItems.iterator(); i.hasNext();) { |
| final IRosterItem item = (IRosterItem) i.next(); |
| if (item instanceof org.eclipse.ecf.presence.roster.RosterGroup) { |
| final org.eclipse.ecf.presence.roster.RosterGroup group = (org.eclipse.ecf.presence.roster.RosterGroup) item; |
| removed = removeItemFromRosterGroup(group, itemIDToRemove); |
| // If group is empty, remove it too |
| if (group.getEntries().size() == 0) |
| i.remove(); |
| } else if (item instanceof org.eclipse.ecf.presence.roster.RosterEntry) { |
| if (((org.eclipse.ecf.presence.roster.RosterEntry) item).getUser().getID().equals(itemIDToRemove)) { |
| i.remove(); |
| removed = true; |
| } |
| } |
| } |
| } |
| if (removed) |
| rosterManager.notifyRosterUpdate(roster); |
| |
| } |
| |
| private boolean removeItemFromRosterGroup(org.eclipse.ecf.presence.roster.RosterGroup group, XMPPID itemIDToRemove) { |
| final Collection groupEntries = group.getEntries(); |
| synchronized (groupEntries) { |
| for (final Iterator i = group.getEntries().iterator(); i.hasNext();) { |
| final org.eclipse.ecf.presence.roster.RosterEntry entry = (org.eclipse.ecf.presence.roster.RosterEntry) i.next(); |
| if (entry.getUser().getID().equals(itemIDToRemove)) { |
| i.remove(); |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| protected void handleMessageEvent(MessageEvent evt) { |
| Message msg = evt.getMessage(); |
| final String from = msg.getFrom(); |
| final String body = msg.getBody(); |
| final String subject = msg.getSubject(); |
| final ID fromID = createIDFromName(from); |
| final ID threadID = createThreadID(msg.getThread()); |
| msg = filterMessageType(msg); |
| if (msg != null) { |
| if (msg.getExtension("composing", //$NON-NLS-1$ |
| "http://jabber.org/protocol/chatstates") != null) { //$NON-NLS-1$ |
| chatManager.fireTypingMessage(fromID, new TypingMessage(fromID, true, body)); |
| } else if (msg.getExtension("paused", //$NON-NLS-1$ |
| "http://jabber.org/protocol/chatstates") != null) { //$NON-NLS-1$ |
| chatManager.fireTypingMessage(fromID, new TypingMessage(fromID, false, body)); |
| } else { |
| final Iterator xhtmlbodies = evt.getXHTMLBodies(); |
| if (xhtmlbodies != null) { |
| final List xhtmlbodylist = new ArrayList(); |
| for (; xhtmlbodies.hasNext();) |
| xhtmlbodylist.add(xhtmlbodies.next()); |
| chatManager.fireXHTMLChatMessage(fromID, threadID, msg.getType(), subject, body, ECFConnection.getPropertiesFromPacket(msg), xhtmlbodylist); |
| } else if (body != null) { |
| chatManager.fireChatMessage(fromID, threadID, msg.getType(), subject, body, ECFConnection.getPropertiesFromPacket(msg)); |
| } |
| } |
| } |
| } |
| |
| protected void handlePresenceEvent(PresenceEvent evt) { |
| final Presence xmppPresence = evt.getPresence(); |
| final String from = xmppPresence.getFrom(); |
| final IPresence newPresence = createIPresence(xmppPresence); |
| final XMPPID fromID = createIDFromName(from); |
| if (newPresence.getType().equals(IPresence.Type.SUBSCRIBE) || newPresence.getType().equals(IPresence.Type.UNSUBSCRIBE) || newPresence.getType().equals(IPresence.Type.SUBSCRIBED) || newPresence.getType().equals(IPresence.Type.UNSUBSCRIBED)) { |
| rosterManager.notifySubscriptionListener(fromID, newPresence); |
| } else { |
| updatePresence(fromID, newPresence); |
| firePresenceListeners(fromID, newPresence); |
| } |
| } |
| |
| private void firePresenceListeners(ID fromID, IPresence presence) { |
| List toNotify = null; |
| synchronized (presenceListeners) { |
| toNotify = new ArrayList(presenceListeners); |
| } |
| for (final Iterator i = toNotify.iterator(); i.hasNext();) { |
| final IPresenceListener l = (IPresenceListener) i.next(); |
| l.handlePresence(fromID, presence); |
| } |
| } |
| |
| private void updatePresence(XMPPID fromID, IPresence newPresence) { |
| final Collection rosterItems = roster.getItems(); |
| synchronized (rosterItems) { |
| for (final Iterator i = roster.getItems().iterator(); i.hasNext();) { |
| final IRosterItem item = (IRosterItem) i.next(); |
| if (item instanceof IRosterGroup) { |
| updatePresenceInGroup((IRosterGroup) item, fromID, newPresence); |
| } else if (item instanceof org.eclipse.ecf.presence.roster.RosterEntry) { |
| updatePresenceForMatchingEntry((org.eclipse.ecf.presence.roster.RosterEntry) item, fromID, newPresence); |
| } |
| } |
| } |
| } |
| |
| private void updatePresenceForMatchingEntry(org.eclipse.ecf.presence.roster.RosterEntry entry, XMPPID fromID, IPresence newPresence) { |
| final IUser user = entry.getUser(); |
| if (fromID.equals(user.getID())) { |
| entry.setPresence(newPresence); |
| rosterManager.notifyRosterUpdate(entry); |
| } |
| } |
| |
| private void updatePresenceInGroup(IRosterGroup group, XMPPID fromID, IPresence newPresence) { |
| final Collection groupEntries = group.getEntries(); |
| synchronized (groupEntries) { |
| for (final Iterator i = group.getEntries().iterator(); i.hasNext();) { |
| updatePresenceForMatchingEntry((org.eclipse.ecf.presence.roster.RosterEntry) i.next(), fromID, newPresence); |
| } |
| } |
| } |
| |
| protected void handleRoster(Roster roster) { |
| for (final Iterator i = roster.getEntries(); i.hasNext();) { |
| final IRosterItem[] items = createRosterEntries((RosterEntry) i.next()); |
| for (int j = 0; j < items.length; j++) { |
| this.roster.addItem(items[j]); |
| } |
| } |
| rosterManager.notifyRosterUpdate(this.roster); |
| } |
| |
| protected XMPPID createIDFromName(String uname) { |
| try { |
| if (uname.indexOf('@') == -1) { |
| return new XMPPID(container.getConnectNamespace(), "admin" + "@" + uname); |
| } |
| return new XMPPID(container.getConnectNamespace(), uname); |
| } catch (final Exception e) { |
| traceStack("Exception in createIDFromName", e); |
| return null; |
| } |
| } |
| |
| protected ID createThreadID(String thread) { |
| try { |
| if (thread == null || thread.equals("")) |
| return null; |
| return IDFactory.getDefault().createStringID(thread); |
| } catch (final Exception e) { |
| traceStack("Exception in createThreadID", e); |
| return null; |
| } |
| |
| } |
| |
| private final Map vcardCache = new WeakHashMap(); |
| |
| private VCard getFromCache(String id) { |
| if (id == null) |
| return null; |
| return (VCard) vcardCache.get(id); |
| } |
| |
| private void addToCache(String id, VCard card) { |
| vcardCache.put(id, card); |
| } |
| |
| private VCard getVCardForPresence(Presence xmppPresence) { |
| VCard result = null; |
| if (xmppPresence.getExtension("x", "vcard-temp:x:update") != null) { |
| final String from = xmppPresence.getFrom(); |
| result = getFromCache(from); |
| if (result == null && from != null) { |
| result = new VCard(); |
| try { |
| result.load(container.getXMPPConnection(), from); |
| addToCache(from, result); |
| } catch (final XMPPException e) { |
| traceStack("vcard loading exception", e); |
| } |
| } |
| } |
| return result; |
| } |
| |
| private Map addVCardProperties(VCard vcard, Map props) { |
| if (vcard == null) |
| return props; |
| final String emailHome = vcard.getEmailHome(); |
| if (emailHome != null && !emailHome.equals("")) |
| props.put(VCARD_EMAIL_HOME, emailHome); |
| final String emailWork = vcard.getEmailWork(); |
| if (emailWork != null && !emailWork.equals("")) |
| props.put(VCARD_EMAIL_WORK, emailWork); |
| final String firstName = vcard.getFirstName(); |
| if (firstName != null && !firstName.equals("")) |
| props.put(VCARD_NAME_FIRST, firstName); |
| final String middleName = vcard.getMiddleName(); |
| if (middleName != null && !middleName.equals("")) |
| props.put(VCARD_NAME_MIDDLE, middleName); |
| final String lastName = vcard.getLastName(); |
| if (lastName != null && !lastName.equals("")) |
| props.put(VCARD_NAME_LAST, lastName); |
| final String nickName = vcard.getNickName(); |
| if (nickName != null && !nickName.equals("")) |
| props.put(VCARD_NAME_NICK, nickName); |
| final String phoneHomeVoice = vcard.getPhoneHome("VOICE"); |
| if (phoneHomeVoice != null && !phoneHomeVoice.equals("")) |
| props.put(VCARD_PHONE_HOME_VOICE, phoneHomeVoice); |
| final String phoneHomeCell = vcard.getPhoneHome("CELL"); |
| if (phoneHomeCell != null && !phoneHomeCell.equals("")) |
| props.put(VCARD_PHONE_HOME_CELL, phoneHomeCell); |
| final String phoneWorkVoice = vcard.getPhoneWork("VOICE"); |
| if (phoneWorkVoice != null && !phoneWorkVoice.equals("")) |
| props.put(VCARD_PHONE_WORK_VOICE, phoneWorkVoice); |
| final String phoneWorkCell = vcard.getPhoneWork("CELL"); |
| if (phoneWorkCell != null && !phoneWorkCell.equals("")) |
| props.put(VCARD_PHONE_WORK_CELL, phoneWorkCell); |
| return props; |
| } |
| |
| class XMPPPresence extends org.eclipse.ecf.presence.Presence { |
| |
| private static final long serialVersionUID = 7843634971520771692L; |
| |
| IAsyncResult asyncResult = null; |
| String fromID = null; |
| |
| XMPPPresence(String fromID, Presence xmppPresence, IAsyncResult future) { |
| super(createIPresenceType(xmppPresence), xmppPresence.getStatus(), createIPresenceMode(xmppPresence), ECFConnection.getPropertiesFromPacket(xmppPresence), null); |
| this.fromID = fromID; |
| } |
| |
| private void fillFromVCard() { |
| VCard card = getFromCache(fromID); |
| if (card == null && asyncResult != null) { |
| try { |
| card = (VCard) asyncResult.get(); |
| asyncResult = null; |
| } catch (final Exception e) { |
| } |
| } |
| if (card != null) { |
| addToCache(fromID, card); |
| final byte[] bytes = card.getAvatar(); |
| this.pictureData = (bytes == null) ? new byte[0] : bytes; |
| this.properties = addVCardProperties(card, this.properties); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ecf.presence.Presence#getPictureData() |
| */ |
| public byte[] getPictureData() { |
| fillFromVCard(); |
| return this.pictureData; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.eclipse.ecf.presence.Presence#getProperties() |
| */ |
| public Map getProperties() { |
| fillFromVCard(); |
| return this.properties; |
| } |
| } |
| |
| protected IPresence createIPresence(final Presence xmppPresence) { |
| final AsyncResult asyncResult = new AsyncResult(); |
| final Thread t = new Thread(asyncResult.setter(new ICallable() { |
| public Object call() throws Throwable { |
| return getVCardForPresence(xmppPresence); |
| } |
| })); |
| t.start(); |
| return new XMPPPresence(xmppPresence.getFrom(), xmppPresence, asyncResult); |
| } |
| |
| protected Presence createPresence(IPresence ipresence) { |
| final Presence newPresence = new Presence(createPresenceType(ipresence), ipresence.getStatus(), 0, createPresenceMode(ipresence)); |
| ECFConnection.setPropertiesInPacket(newPresence, ipresence.getProperties()); |
| return newPresence; |
| } |
| |
| 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.DO_NOT_DISTURB) { |
| return IPresence.Mode.DND; |
| } else if (mode == Presence.Mode.EXTENDED_AWAY) { |
| return IPresence.Mode.EXTENDED_AWAY; |
| } else if (mode == Presence.Mode.INVISIBLE) { |
| return IPresence.Mode.INVISIBLE; |
| } |
| return IPresence.Mode.AVAILABLE; |
| } |
| |
| protected Presence.Mode createPresenceMode(IPresence ipresence) { |
| if (ipresence == null) |
| return Presence.Mode.AVAILABLE; |
| final IPresence.Mode mode = ipresence.getMode(); |
| if (mode == IPresence.Mode.AVAILABLE) { |
| return Presence.Mode.AVAILABLE; |
| } else if (mode == IPresence.Mode.AWAY) { |
| return Presence.Mode.AWAY; |
| } else if (mode == IPresence.Mode.CHAT) { |
| return Presence.Mode.CHAT; |
| } else if (mode == IPresence.Mode.DND) { |
| return Presence.Mode.DO_NOT_DISTURB; |
| } else if (mode == IPresence.Mode.EXTENDED_AWAY) { |
| return Presence.Mode.EXTENDED_AWAY; |
| } else if (mode == IPresence.Mode.INVISIBLE) { |
| return Presence.Mode.INVISIBLE; |
| } |
| return Presence.Mode.AVAILABLE; |
| } |
| |
| 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 Presence.Type createPresenceType(IPresence ipresence) { |
| if (ipresence == null) |
| return Presence.Type.AVAILABLE; |
| final IPresence.Type type = ipresence.getType(); |
| if (type == IPresence.Type.AVAILABLE) { |
| return Presence.Type.AVAILABLE; |
| } else if (type == IPresence.Type.ERROR) { |
| return Presence.Type.ERROR; |
| } else if (type == IPresence.Type.SUBSCRIBE) { |
| return Presence.Type.SUBSCRIBE; |
| } else if (type == IPresence.Type.SUBSCRIBED) { |
| return Presence.Type.SUBSCRIBED; |
| } else if (type == IPresence.Type.UNSUBSCRIBE) { |
| return Presence.Type.UNSUBSCRIBE; |
| } else if (type == IPresence.Type.UNSUBSCRIBED) { |
| return Presence.Type.UNSUBSCRIBED; |
| } else if (type == IPresence.Type.UNAVAILABLE) { |
| return Presence.Type.UNAVAILABLE; |
| } |
| return Presence.Type.AVAILABLE; |
| } |
| |
| protected IRosterItem[] createRosterEntries(RosterEntry entry) { |
| return createRosterEntries(entry.getGroups(), roster, new User(createIDFromName(entry.getUser()), entry.getName())); |
| } |
| |
| private IRosterItem[] createRosterEntries(Iterator grps, IRosterItem parent, IUser user) { |
| final List result = new ArrayList(); |
| if (grps.hasNext()) { |
| for (; grps.hasNext();) { |
| final Object o = grps.next(); |
| // Get group name |
| final String groupName = (o instanceof String) ? (String) o : ((RosterGroup) o).getName(); |
| |
| if (groupName == null || groupName.equals("")) { |
| createRosterEntries(parent, user, result); |
| continue; |
| } |
| // See if group is already in roster |
| org.eclipse.ecf.presence.roster.RosterGroup rosterGroup = findRosterGroup(parent, groupName); |
| // Set flag if not |
| final boolean groupFound = rosterGroup != null; |
| if (!groupFound) |
| rosterGroup = new org.eclipse.ecf.presence.roster.RosterGroup(parent, groupName); |
| |
| if (findRosterEntry(rosterGroup, user) == null) { |
| // Now create new roster entry |
| new org.eclipse.ecf.presence.roster.RosterEntry(rosterGroup, user, new org.eclipse.ecf.presence.Presence(IPresence.Type.UNAVAILABLE, IPresence.Type.UNAVAILABLE.toString(), IPresence.Mode.AWAY)); |
| } |
| // Only add localGrp if not already in list |
| if (!groupFound) |
| result.add(rosterGroup); |
| } |
| } else |
| createRosterEntries(parent, user, result); |
| return (IRosterItem[]) result.toArray(new IRosterItem[] {}); |
| } |
| |
| protected IRosterEntry createRosterEntry(ID userID, String name, Iterator grps) { |
| final List groups = new ArrayList(); |
| for (; grps.hasNext();) { |
| final Object o = grps.next(); |
| final String groupName = (o instanceof String) ? (String) o : ((RosterGroup) o).getName(); |
| final IRosterGroup localGrp = new org.eclipse.ecf.presence.roster.RosterGroup(roster, groupName); |
| groups.add(localGrp); |
| } |
| final IUser user = new User(userID, name); |
| IRosterEntry newEntry = null; |
| if (groups.size() == 0) |
| return new org.eclipse.ecf.presence.roster.RosterEntry(roster, user, null); |
| else |
| for (int i = 0; i < groups.size(); i++) { |
| final IRosterGroup grp = (IRosterGroup) groups.get(i); |
| if (i == 0) |
| newEntry = new org.eclipse.ecf.presence.roster.RosterEntry(grp, user, null); |
| else { |
| grp.getEntries().add(newEntry); |
| newEntry.getGroups().add(grp); |
| } |
| } |
| return newEntry; |
| } |
| |
| private void createRosterEntries(IRosterItem parent, IUser user, List result) { |
| final org.eclipse.ecf.presence.roster.RosterEntry oldEntry = findRosterEntry((org.eclipse.ecf.presence.roster.RosterGroup) null, user); |
| if (oldEntry == null) { |
| final org.eclipse.ecf.presence.roster.RosterEntry newEntry = new org.eclipse.ecf.presence.roster.RosterEntry(parent, user, new org.eclipse.ecf.presence.Presence(IPresence.Type.UNAVAILABLE, IPresence.Type.UNAVAILABLE.toString(), IPresence.Mode.AWAY)); |
| result.add(newEntry); |
| } |
| } |
| |
| private org.eclipse.ecf.presence.roster.RosterEntry findRosterEntry(org.eclipse.ecf.presence.roster.RosterGroup rosterGroup, IUser user) { |
| if (rosterGroup != null) |
| return findRosterEntry(rosterGroup.getEntries(), user); |
| else |
| return findRosterEntry(roster.getItems(), user); |
| } |
| |
| private org.eclipse.ecf.presence.roster.RosterEntry findRosterEntry(Collection entries, IUser user) { |
| for (final Iterator i = entries.iterator(); i.hasNext();) { |
| final Object o = i.next(); |
| if (o instanceof org.eclipse.ecf.presence.roster.RosterEntry) { |
| final org.eclipse.ecf.presence.roster.RosterEntry entry = (org.eclipse.ecf.presence.roster.RosterEntry) o; |
| if (entry.getUser().getID().equals(user.getID())) |
| return entry; |
| } |
| } |
| return null; |
| } |
| |
| protected IRosterItem[] createRosterEntries(RosterPacket.Item entry) { |
| final XMPPID id = createIDFromName(entry.getUser()); |
| String name = entry.getName(); |
| if (name == null) |
| name = id.getUsername(); |
| return createRosterEntries(entry.getGroupNames(), roster, new User(id, name)); |
| } |
| |
| protected org.eclipse.ecf.presence.roster.RosterGroup findRosterGroup(Object parent, String grp) { |
| final Collection items = roster.getItems(); |
| for (final Iterator i = items.iterator(); i.hasNext();) { |
| final IRosterItem item = (IRosterItem) i.next(); |
| if (item.getName().equals(grp)) |
| return (org.eclipse.ecf.presence.roster.RosterGroup) item; |
| } |
| return null; |
| } |
| |
| // utility methods |
| |
| protected ECFConnection getConnectionOrThrowIfNull() throws IOException { |
| final ECFConnection conn = container.getECFConnection(); |
| if (conn == null) |
| throw new IOException("Not connected"); |
| return conn; |
| } |
| |
| protected void traceAndThrowECFException(String msg, Throwable t) throws ECFException { |
| throw new ECFException(msg, t); |
| } |
| |
| protected void trace(String msg) { |
| |
| } |
| |
| protected void traceStack(String msg, Throwable e) { |
| |
| } |
| |
| protected ID createRoomIDFromName(String from) { |
| try { |
| final ECFConnection ecfConnection = getConnectionOrThrowIfNull(); |
| return new XMPPRoomID(container.getConnectNamespace(), ecfConnection.getXMPPConnection(), from); |
| } catch (final Exception e) { |
| traceStack("Exception in createRoomIDFromName", e); |
| return null; |
| } |
| } |
| |
| protected ID createUserIDFromName(String name) { |
| ID result = null; |
| try { |
| result = new XMPPID(container.getConnectNamespace(), name); |
| return result; |
| } catch (final Exception e) { |
| traceStack("Exception in createIDFromName", e); |
| return null; |
| } |
| } |
| |
| protected Message.Type[] ALLOWED_MESSAGES = {Message.Type.CHAT, Message.Type.ERROR, Message.Type.HEADLINE, Message.Type.NORMAL}; |
| |
| 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; |
| } |
| |
| /** |
| * @return chat manager. |
| */ |
| public IChatManager getChatManager() { |
| return chatManager; |
| } |
| |
| } |