[sip-comm-cvs] CVS update: /sip-communicator/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetMultiUserChatJabberImpl.java

emcho at dev.java.net emcho at dev.java.net
Mon Apr 23 20:12:20 CEST 2007


User: emcho   
Date: 2007-04-23 18:12:20+0000
Log:
 working on multi chat and a jabber implementation
 
 basic multichat functionality

File Changes:

Directory: /sip-communicator/src/net/java/sip/communicator/impl/protocol/jabber/
================================================================================

File [changed]: OperationSetMultiUserChatJabberImpl.java
Url: https://sip-communicator.dev.java.net/source/browse/sip-communicator/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetMultiUserChatJabberImpl.java?r1=1.2&r2=1.3
Delta lines:  +326 -93
----------------------
--- OperationSetMultiUserChatJabberImpl.java	2007-03-10 14:33:38+0000	1.2
+++ OperationSetMultiUserChatJabberImpl.java	2007-04-23 18:12:18+0000	1.3
@@ -15,6 +15,7 @@
 import org.jivesoftware.smackx.muc.MultiUserChat;
 import org.jivesoftware.smackx.muc.RoomInfo;
 import org.jivesoftware.smack.packet.*;
+import org.jivesoftware.smackx.muc.HostedRoom;
 
 /**
  * A jabber implementation of the multi user chat operation set.
@@ -44,10 +45,11 @@
     private Vector invitationRejectionListeners = new Vector();
 
     /**
-     * A list of the rooms that are currently open by this account. (We have
-     * not necessarily joined these rooms).
+     * A list of the rooms that are currently open by this account. Note that
+     * we have not necessarily joined these rooms, we might have simply been
+     * searching through them.
      */
-    private Vector currentlyOpenChatRooms = new Vector();
+    private Hashtable chatRoomCache = new Hashtable();
 
     /**
      * Instantiates the user operation set with a currently valid instance of
@@ -60,7 +62,6 @@
     {
         this.jabberProvider = jabberProvider;
 
-//        throw new RuntimeException("implement invitation listeners");
         /** @todo implement invitation listeners */
 //        MultiUserChat.addInvitationListener(jabberProvider.getConnection()
 //                                            , this);
@@ -146,79 +147,58 @@
     public ChatRoom createChatRoom(String roomName, Hashtable roomProperties)
         throws OperationFailedException, OperationNotSupportedException
     {
-        if(MultiUserChat.isServiceEnabled(
-            getXmppConnection()
-            , jabberProvider.getAccountID().getUserID()))
-        {
-            throw new OperationNotSupportedException(
-                "Impossible to create chat rooms on server "
-                + jabberProvider.getAccountID().getService()
-                + " for user "
-                + jabberProvider.getAccountID().getUserID());
-        }
+        //first make sure we are connected and the server supports multichat
+        assertSupportedAndConnected();
 
-        //retrieve room info in order to determine whether the room actually
-        //exists
-//        RoomInfo roomInfo = null;
-//        try
-//        {
-//            roomInfo
-//                = MultiUserChat.getRoomInfo(getXmppConnection(), roomName);
-//            logger.error("RoomInfo=" + roomInfo.toString());
-//        }
-//        catch (XMPPException ex)
-//        {
-//            logger.error("Failed to retrieve room info.", ex);
-//            if(ex.getXMPPError().getCode() == 404)
-//                logger.warn("niama iaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
-//            throw new OperationFailedException("Failed to retrieve room info."
-//                      , OperationFailedException.GENERAL_ERROR
-//                      , ex);
-//        }
-//
-        MultiUserChat muc
-            = new MultiUserChat(getXmppConnection(), roomName);
+        //make sure we have the complete room name.
+        roomName = getCanonicalRoomName(roomName);
 
-        try
-        {
-            logger.error("MUCI=" + muc.toString());
-            logger.debug("muc.getRoom()=" + muc.getRoom());
-            logger.debug("muc.getConfigurationForm();=" +
-                         muc.getConfigurationForm());
-            logger.debug("muc.getSubject();=" + muc.getSubject());
-            logger.debug("muc.getOwners();=" + muc.getOwners());
-//            muc.is
-        }
-        catch (XMPPException ex2)
-        {
-            ex2.printStackTrace(System.out);
-            throw new OperationFailedException("", 0, ex2);
-        }
+        //check if the room hasn't been created already
+        ChatRoom room = findRoom(roomName);
+
+        if(room != null)
+            throw new OperationFailedException(
+                            "There is already a room with"
+                            , OperationFailedException.IDENTIFICATION_CONFLICT);
+
+        MultiUserChat muc = new MultiUserChat(getXmppConnection(), roomName);
 
 
         try
         {
-            try
-            {
-                muc.create("kiki");
+            muc.create(getXmppConnection().getUser());
             }
-            catch (XMPPException ex1)
+        catch (XMPPException ex)
             {
+            logger.error("Failed to create chat room.", ex);
+            throw new OperationFailedException("Failed to create chat room"
+                                               , ex.getXMPPError().getCode()
+                                               , ex.getCause());
             }
-            muc.join("kiki");
-            muc.sendMessage("created a room");
+        return createLocalChatRoomInstance(muc);
         }
-        catch (XMPPException ex)
+
+    /**
+     * Creates a <tt>ChatRoom</tt> from the specified smack
+     * <tt>MultiUserChat</tt>.
+     *
+     * @param muc the smack MultiUserChat instance that we're going to wrap our
+     * chat room around.
+     *
+     * @return ChatRoom the chat room that we've just created.
+     */
+    private ChatRoom createLocalChatRoomInstance(MultiUserChat muc)
         {
-            logger.error("Failed to create or join a chat room", ex);
-            throw new OperationFailedException(
-                "Failed to create or join a chat room"
-                , OperationFailedException.FORBIDDEN);
-        }
+        synchronized(chatRoomCache)
+        {
+            ChatRoomJabberImpl chatRoom
+                = new ChatRoomJabberImpl(muc, jabberProvider);
+            cacheChatRoom(chatRoom);
 
-        ChatRoomJabberImpl chatRoom = new ChatRoomJabberImpl(muc);
         return chatRoom;
     }
+    }
+
 
     /**
      * Returns a reference to a chatRoom named <tt>roomName</tt> or null if
@@ -229,14 +209,65 @@
      * @return the <tt>ChatRoom</tt> named <tt>roomName</tt> or null if no
      *   such room exists on the server that this provider is currently
      *   connected to.
-     * @todo Implement this
-     *   net.java.sip.communicator.service.protocol.OperationSetMultiUserChat
-     *   method
+     * @throws OperationFailedException if an error occurs while trying to
+     * discover the room on the server.
+     * @throws OperationNotSupportedException if the server does not support
+     * multi user chat
      */
     public ChatRoom findRoom(String roomName)
+        throws OperationFailedException, OperationNotSupportedException
+    {
+        //make sure we are connected and multichat is supported.
+        assertSupportedAndConnected();
+
+        //first check whether we have already initialized the room.
+        ChatRoom room = (ChatRoom)chatRoomCache.get(roomName);
+
+        //if yes - we return it
+        if(room != null)
+        {
+            return room;
+        }
+        //if not, then check whether it's on the server and if yes - create it
+        //locally.
+        else
+        {
+            try
+            {
+                MultiUserChat.getRoomInfo( getXmppConnection(), roomName );
+
+                //if we get here then we didn't get an error while retrieving
+                //room info and we can assume it exists
+                return createLocalChatRoomInstance(
+                    new MultiUserChat(getXmppConnection(),roomName));
+            }
+            catch (XMPPException ex)
+            {
+                //if this is a 404 then it simply means the room doesn't exist
+                //on the server, so we return null and don't rethrow the
+                //exception
+                if(ex.getXMPPError() != null
+                   && ex.getXMPPError().getCode() == 404)
     {
         return null;
     }
+                logger.error(
+                    "Failed to retrieve room info for "
+                    + roomName
+                    +". Error was: "
+                    + ex.getMessage()
+                    , ex);
+
+                //otherwise we rethrow the exception cause it means a real error
+                throw new OperationFailedException(
+                    "Failed to retrieve room info for "
+                    + roomName
+                    +". Error was: "
+                    + ex.getMessage()
+                    , OperationFailedException.GENERAL_ERROR);
+            }
+        }
+    }
 
     /**
      * Returns a list of the chat rooms that we have joined and are currently
@@ -244,49 +275,130 @@
      *
      * @return a <tt>List</tt> of the rooms where the user has joined using
      *   a given connection.
-     * @todo Implement this
-     *   net.java.sip.communicator.service.protocol.OperationSetMultiUserChat
-     *   method
      */
     public List getCurrentlyJoinedChatRooms()
     {
-        return null;
+        synchronized(chatRoomCache)
+        {
+            List joinedRooms
+                = new LinkedList(this.chatRoomCache.entrySet());
+
+            Iterator joinedRoomsIter = joinedRooms.iterator();
+
+            while (joinedRoomsIter.hasNext())
+            {
+                if ( !( (ChatRoom) joinedRoomsIter.next()).isJoined())
+                    joinedRoomsIter.remove();
+            }
+
+            return joinedRooms;
+        }
     }
 
     /**
-     * Returns a list of the chat rooms that <tt>contact</tt> has joined and
-     * is currently active in.
+     * Returns a list of the names of all chat rooms that <tt>contact</tt> is
+     * currently a  member of.
      *
      * @param contact the contact whose current ChatRooms we will be
      *   querying.
-     * @return a list of the chat rooms that <tt>contact</tt> has joined and
-     *   is currently active in.
-     * @todo Implement this
-     *   net.java.sip.communicator.service.protocol.OperationSetMultiUserChat
-     *   method
+     * @return a list of <tt>String</tt> indicating tha names of  the chat rooms
+     * that <tt>contact</tt> has joined and is currently active in.
+     *
+     * @throws OperationFailedException if an error occurs while trying to
+     * discover the room on the server.
+     * @throws OperationNotSupportedException if the server does not support
+     * multi user chat
      */
     public List getCurrentlyJoinedChatRooms(Contact contact)
+        throws OperationFailedException, OperationNotSupportedException
     {
-        return null;
+        assertSupportedAndConnected();
+
+        Iterator joinedRoomsIter
+            = MultiUserChat.getJoinedRooms( getXmppConnection()
+                                            , contact.getAddress());
+
+        List joinedRoomsForContact = new LinkedList();
+
+        while ( joinedRoomsIter.hasNext() )
+        {
+            MultiUserChat muc = (MultiUserChat)joinedRoomsIter.next();
+            joinedRoomsForContact.add(muc.getRoom());
+        }
+
+        return joinedRoomsForContact;
     }
 
     /**
-     * Returns the <tt>List</tt> of <tt>ChatRoom</tt>s currently available on
-     * the server that this protocol provider is connected to.
-     *
-     * @return a <tt>java.util.List</tt> of <tt>ChatRoom</tt>s that are
+     * Returns the <tt>List</tt> of <tt>String</tt>s indicating chat rooms
      *   currently available on the server that this protocol provider is
      *   connected to.
-     * @throws OperationFailedException if we faile retrieving this list
-     *   from the server.
-     * @todo Implement this
-     *   net.java.sip.communicator.service.protocol.OperationSetMultiUserChat
-     *   method
+     *
+     * @return a <tt>java.util.List</tt> of the name <tt>String</tt>s for chat
+     * rooms that are currently available on the server that this protocol
+     * provider is connected to.
+     *
+     * @throws OperationFailedException if we faile retrieving this list from
+     * the server.
+     * @throws OperationNotSupportedException if the server does not support
+     * multi user chat
      */
     public List getExistingChatRooms()
-        throws OperationFailedException
+        throws OperationFailedException, OperationNotSupportedException
     {
-        return null;
+        List list = new LinkedList();
+
+        //first retrieve all conference service names available on this server
+        Iterator serviceNames = null;
+        try
+        {
+            serviceNames = MultiUserChat
+                .getServiceNames(getXmppConnection()).iterator();
+        }
+        catch (XMPPException ex)
+        {
+            throw new OperationFailedException(
+                "Failed to retrieve Jabber conference service names"
+                , OperationFailedException.GENERAL_ERROR
+                , ex);
+        }
+
+        //now retrieve all chat rooms currently available for every service name
+        while(serviceNames.hasNext())
+        {
+            String serviceName = (String)serviceNames.next();
+            List roomsOnThisService = new LinkedList();
+
+            try
+            {
+                roomsOnThisService
+                    .addAll(MultiUserChat.getHostedRooms(getXmppConnection()
+                                                         , serviceName));
+            }
+            catch (XMPPException ex)
+            {
+                logger.error("Failed to retrieve rooms for serviceName="
+                             + serviceName);
+                //continue bravely with other service names
+                continue;
+            }
+
+            //now go through all rooms available on this service
+            Iterator serviceRoomsIter = roomsOnThisService.iterator();
+
+            while(serviceRoomsIter.hasNext())
+            {
+                HostedRoom hostedRoom = (HostedRoom)serviceRoomsIter.next();
+
+                //add the room name to the list of names we are returning
+                list.add(hostedRoom.getJid());
+            }
+        }
+
+        /** @todo maybe we should add a check here and fail if retrieving chat
+         * rooms failed for all service names*/
+
+        return list;
     }
 
     /**
@@ -330,4 +442,125 @@
             ? null
             :jabberProvider.getConnection();
     }
+
+    /**
+     * Makes sure that we are properly connected and that the server supports
+     * multi user chats.
+     *
+     * @throws OperationFailedException if the provider is not registered or
+     * the xmpp connection not connected.
+     * @throws OperationNotSupportedException if the service is not supported
+     * by the server.
+     */
+    private void assertSupportedAndConnected()
+        throws OperationFailedException, OperationNotSupportedException
+    {
+        //throw an exception if the provider is not registered or the xmpp
+        //connection not connected.
+        if( !jabberProvider.isRegistered()
+            || !getXmppConnection().isConnected())
+        {
+            throw new OperationFailedException(
+                "Provider not connected to jabber server"
+                , OperationFailedException.NETWORK_FAILURE);
+        }
+
+        //throw an exception if the service is not supported by the server.
+        if(MultiUserChat.isServiceEnabled(
+            getXmppConnection()
+            , jabberProvider.getAccountID().getUserID()))
+        {
+            throw new OperationNotSupportedException(
+                "Chat rooms not supported on server "
+                + jabberProvider.getAccountID().getService()
+                + " for user "
+                + jabberProvider.getAccountID().getUserID());
+        }
+
+    }
+
+    /**
+     * In case <tt>roomName</tt> does not represent a complete room id, the
+     * method returns a canonincal chat room name in the following form:
+     * roomName at muc-servicename.jabserver.com. In case <tt>roomName</tt> is
+     * already a canonical room name, the method simply returns it without
+     * changing it.
+     *
+     * @param roomName the name of the room that we'd like to "canonize".
+     *
+     * @return the canonincal name of the room (which might be equal to
+     * roomName in case it was already in a canonical format).
+     *
+     * @throws OperationFailedException if we fail retrieving the conference
+     * service name
+     */
+    private String getCanonicalRoomName(String roomName)
+        throws OperationFailedException
+    {
+
+        if (roomName.indexOf('@') > 0)
+            return roomName;
+
+        Iterator serviceNamesIter = null;
+        try
+        {
+            serviceNamesIter
+                = MultiUserChat.getServiceNames(getXmppConnection()).iterator();
+        }
+        catch (XMPPException ex)
+        {
+            logger.error("Failed to retrieve conference service name for user: "
+                + jabberProvider.getAccountID().getUserID()
+                + " on server: "
+                + jabberProvider.getAccountID().getService()
+                , ex);
+            throw new OperationFailedException(
+                "Failed to retrieve conference service name for user: "
+                + jabberProvider.getAccountID().getUserID()
+                + " on server: "
+                + jabberProvider.getAccountID().getService()
+                , OperationFailedException.GENERAL_ERROR
+                , ex);
+
+        }
+
+        while( serviceNamesIter.hasNext() )
+        {
+            return roomName
+                + "@"
+                + (String)serviceNamesIter.next()
+                + jabberProvider.getAccountID().getService();
+        }
+
+        //hmmmm strange.. no service name returned. we should probably throw an
+        //exception
+        throw new OperationFailedException(
+            "Failed to retrieve MultiUserChat service names."
+            , OperationFailedException.GENERAL_ERROR);
+    }
+
+    /**
+     * Adds <tt>chatRoom</tt> to the cache of chat rooms that this operation
+     * set is handling.
+     *
+     * @param chatRoom the <tt>ChatRoom</tt> to cache.
+     */
+    private void cacheChatRoom(ChatRoom chatRoom)
+    {
+        this.chatRoomCache.put(chatRoom.getName(), chatRoom);
+    }
+
+    /**
+     * Returns a reference to the chat room named <tt>chatRoomName</tt> or
+     * null if the room hasn't been cached yet.
+     *
+     * @param chatRoomName the name of the room we're looking for.
+     *
+     * @return the <tt>ChatRoomJabberImpl</tt> instance that has been cached
+     * for <tt>chatRoomName</tt> or null if no such room has been cached so far.
+     */
+    public ChatRoomJabberImpl getChatRoom(String chatRoomName)
+    {
+        return (ChatRoomJabberImpl)this.chatRoomCache.get(chatRoomName);
+    }
 }




---------------------------------------------------------------------
To unsubscribe, e-mail: cvs-unsubscribe at sip-communicator.dev.java.net
For additional commands, e-mail: cvs-help at sip-communicator.dev.java.net





More information about the commits mailing list