/** * $RCSfile: ,v $ * $Revision: $ * $Date: $ * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jivesoftware.spark.ui.conferences; import java.awt.Component; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.Iterator; import java.util.List; import javax.swing.JOptionPane; import org.jivesoftware.resource.Res; import org.jivesoftware.resource.SparkRes; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smackx.Form; import org.jivesoftware.smackx.FormField; import org.jivesoftware.smackx.ServiceDiscoveryManager; import org.jivesoftware.smackx.bookmark.BookmarkManager; import org.jivesoftware.smackx.bookmark.BookmarkedConference; import org.jivesoftware.smackx.muc.HostedRoom; import org.jivesoftware.smackx.muc.MultiUserChat; import org.jivesoftware.smackx.muc.RoomInfo; import org.jivesoftware.smackx.packet.DataForm; import org.jivesoftware.smackx.packet.DiscoverInfo; import org.jivesoftware.spark.ChatManager; import org.jivesoftware.spark.SparkManager; import org.jivesoftware.spark.component.PasswordDialog; import org.jivesoftware.spark.ui.ChatRoomNotFoundException; import org.jivesoftware.spark.ui.rooms.GroupChatRoom; import org.jivesoftware.spark.util.ModelUtil; import org.jivesoftware.spark.util.SwingWorker; import org.jivesoftware.spark.util.UIComponentRegistry; import org.jivesoftware.spark.util.log.Log; import org.jivesoftware.sparkimpl.settings.local.LocalPreferences; import org.jivesoftware.sparkimpl.settings.local.SettingsManager; /** * ConferenceUtils allow for basic joining and inviting of users. */ public class ConferenceUtils { private ConferenceUtils() { } /** * Return a list of available Conference rooms from the server * based on the service name. * * @param serviceName the service name (ex. conference@jivesoftware.com) * @return a collection of rooms. * @throws Exception if an error occured during fetch. */ public static Collection<HostedRoom> getRoomList(String serviceName) throws Exception { return MultiUserChat.getHostedRooms(SparkManager.getConnection(), serviceName); } /** * Return the number of occupants in a room. * * @param roomJID the full JID of the conference room. (ex. dev@conference.jivesoftware.com) * @return the number of occupants in the room if available. * @throws XMPPException thrown if an error occured during retrieval of the information. */ public static int getNumberOfOccupants(String roomJID) throws XMPPException { final RoomInfo roomInfo = MultiUserChat.getRoomInfo(SparkManager.getConnection(), roomJID); return roomInfo.getOccupantsCount(); } /** * Retrieve the date (in yyyyMMdd) format of the time the room was created. * * @param roomJID the jid of the room. * @return the formatted date. * @throws Exception throws an exception if we are unable to retrieve the date. */ public static String getCreationDate(String roomJID) throws Exception { ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(SparkManager.getConnection()); final DateFormat dateFormatter = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss"); DiscoverInfo infoResult = discoManager.discoverInfo(roomJID); DataForm dataForm = (DataForm)infoResult.getExtension("x", "jabber:x:data"); if (dataForm == null) { return "Not available"; } Iterator<FormField> fieldIter = dataForm.getFields(); String creationDate = ""; while (fieldIter.hasNext()) { FormField field = fieldIter.next(); String label = field.getLabel(); if (label != null && "Creation date".equalsIgnoreCase(label)) { Iterator<String> valueIterator = field.getValues(); while (valueIterator.hasNext()) { Object oo = valueIterator.next(); creationDate = "" + oo; Date date = dateFormatter.parse(creationDate); creationDate = DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.MEDIUM).format(date); } } } return creationDate; } public static void joinConferenceOnSeperateThread(final String roomName, String roomJID, String password) { joinConferenceOnSeperateThread(roomName, roomJID, password, null, null); } /** * Joins a conference room using another thread. This allows for a smoother opening of rooms. * * @param roomName the name of the room. * @param roomJID the jid of the room. * @param password the rooms password if required. */ public static void joinConferenceOnSeperateThread(final String roomName, String roomJID, String password, final String message, final Collection<String> jids) { ChatManager chatManager = SparkManager.getChatManager(); LocalPreferences pref = SettingsManager.getLocalPreferences(); final MultiUserChat groupChat = new MultiUserChat(SparkManager.getConnection(), roomJID); final String nickname = pref.getNickname().trim(); // Check if room already exists. If so, join room again. try { GroupChatRoom chatRoom = (GroupChatRoom)chatManager.getChatContainer().getChatRoom(roomJID); MultiUserChat muc = chatRoom.getMultiUserChat(); chatRoom.setPassword(password); if (!muc.isJoined()) { joinRoom(muc, nickname, password); } chatManager.getChatContainer().activateChatRoom(chatRoom); invite(groupChat, chatRoom, jids, message); return; } catch (ChatRoomNotFoundException e) { // Nothing to do } final GroupChatRoom room = UIComponentRegistry.createGroupChatRoom(groupChat); room.setTabTitle(roomName); room.setPassword(password); if (isPasswordRequired(roomJID) && password == null) { final PasswordDialog passwordDialog = new PasswordDialog(); password = passwordDialog.getPassword(Res.getString("title.password.required"), Res.getString("message.groupchat.require.password"), SparkRes.getImageIcon(SparkRes.LOCK_16x16), SparkManager.getFocusedComponent()); room.setPassword(password); if (!ModelUtil.hasLength(password)) { return; } } final List<String> errors = new ArrayList<String>(); final String userPassword = password; final SwingWorker startChat = new SwingWorker() { public Object construct() { if (!groupChat.isJoined()) { int groupChatCounter = 0; while (true) { groupChatCounter++; String joinName = nickname; if (groupChatCounter > 1) { joinName = joinName + groupChatCounter; } if (groupChatCounter < 10) { try { if (ModelUtil.hasLength(userPassword)) { groupChat.join(joinName, userPassword); } else { groupChat.join(joinName); } break; } catch (XMPPException ex) { int code = 0; if (ex.getXMPPError() != null) { code = ex.getXMPPError().getCode(); } if (code == 0) { errors.add("No response from server."); } else if (code == 401) { errors.add("The password did not match the rooms password."); } else if (code == 403) { errors.add("You have been banned from this room."); } else if (code == 404) { errors.add("The room you are trying to enter does not exist."); } else if (code == 407) { errors.add("You are not a member of this room.\nThis room requires you to be a member to join."); } else if (code != 409) { break; } } } else { break; } } } invite(groupChat, room, jids, message); return "ok"; } public void finished() { if (errors.size() > 0) { String error = errors.get(0); JOptionPane.showMessageDialog(SparkManager.getMainWindow(), error, "Unable to join the room at this time.", JOptionPane.ERROR_MESSAGE); } else if (groupChat.isJoined()) { ChatManager chatManager = SparkManager.getChatManager(); chatManager.getChatContainer().addChatRoom(room); chatManager.getChatContainer().activateChatRoom(room); } else { JOptionPane.showMessageDialog(SparkManager.getMainWindow(), "Unable to join the room.", "Error", JOptionPane.ERROR_MESSAGE); } } }; startChat.start(); } private static void invite(MultiUserChat groupChat, GroupChatRoom room, Collection<String> jids, String message) { if (jids != null && message != null) { for (String jid : jids) { groupChat.invite(jid, message); room.getTranscriptWindow().insertNotificationMessage( Res.getString("message.waiting.for.user.to.join", jid), ChatManager.NOTIFICATION_COLOR); } } } /** * Presents the user with a dialog pre-filled with the room name and the jid. * * @param roomName the name of the room. * @param roomJID the rooms jid. */ public static void joinConferenceRoom(final String roomName, String roomJID) { JoinConferenceRoomDialog joinDialog = new JoinConferenceRoomDialog(); joinDialog.joinRoom(roomJID, roomName); } /** * Joins a chat room without using the UI. * * @param groupChat the <code>MultiUserChat</code> * @param nickname the nickname of the user. * @param password the password to join the room with. * @return a List of errors, if any. */ public static List<String> joinRoom(MultiUserChat groupChat, String nickname, String password) { final List<String> errors = new ArrayList<String>(); if (!groupChat.isJoined()) { int groupChatCounter = 0; while (true) { groupChatCounter++; String joinName = nickname; if (groupChatCounter > 1) { joinName = joinName + groupChatCounter; } if (groupChatCounter < 10) { try { if (ModelUtil.hasLength(password)) { groupChat.join(joinName, password); } else { groupChat.join(joinName); } break; } catch (XMPPException ex) { int code = 0; if (ex.getXMPPError() != null) { code = ex.getXMPPError().getCode(); } if (code == 0) { errors.add("No response from server."); } else if (code == 401) { errors.add("A Password is required to enter this room."); } else if (code == 403) { errors.add("You have been banned from this room."); } else if (code == 404) { errors.add("The room you are trying to enter does not exist."); } else if (code == 407) { errors.add("You are not a member of this room.\nThis room requires you to be a member to join."); } else if (code != 409) { break; } } } else { break; } } } return errors; } /** * Invites users to an existing room. * * @param serviceName the service name to use. * @param roomName the name of the room. * @param jids a collection of the users to invite. */ public static void inviteUsersToRoom(String serviceName, String roomName, Collection<String> jids, boolean randomName) { final LocalPreferences pref = SettingsManager.getLocalPreferences(); boolean useTextField = pref.isUseAdHocRoom(); Collection<BookmarkedConference> rooms = null; if (!useTextField) { try { rooms = retrieveBookmarkedConferences(); } catch (Exception ex) { Log.error(ex); } useTextField = !randomName || (rooms == null || rooms.size() == 0); } InvitationDialog inviteDialog = new InvitationDialog(useTextField); inviteDialog.inviteUsersToRoom(serviceName, rooms, roomName, jids); } public static Collection<BookmarkedConference> retrieveBookmarkedConferences() throws XMPPException { BookmarkManager manager = BookmarkManager.getBookmarkManager(SparkManager.getConnection()); return manager.getBookmarkedConferences(); } /** * Returns true if the room requires a password. * * @param roomJID the JID of the room. * @return true if the room requires a password. */ public static boolean isPasswordRequired(String roomJID) { // Check to see if the room is password protected ServiceDiscoveryManager discover = ServiceDiscoveryManager.getInstanceFor(SparkManager.getConnection()); try { DiscoverInfo info = discover.discoverInfo(roomJID); return info.containsFeature("muc_passwordprotected"); } catch (XMPPException e) { Log.error(e); } return false; } /** * Creates a private conference. * * @param serviceName the service name to use for the private conference. * @param message the message sent to each individual invitee. * @param roomName the name of the room to create. * @param jids a collection of the user JIDs to invite. * @throws XMPPException thrown if an error occurs during room creation. */ public static void createPrivateConference(String serviceName, String message, String roomName, Collection<String> jids) throws XMPPException { final String roomJID = StringUtils.escapeNode(roomName) + "@" + serviceName; final MultiUserChat multiUserChat = new MultiUserChat(SparkManager.getConnection(), roomJID); final LocalPreferences pref = SettingsManager.getLocalPreferences(); final GroupChatRoom room = UIComponentRegistry.createGroupChatRoom(multiUserChat); try { // Attempt to create room. multiUserChat.create(pref.getNickname()); } catch (XMPPException e) { throw new XMPPException(e); } try { // Since this is a private room, make the room not public and set user as owner of the room. Form submitForm = multiUserChat.getConfigurationForm().createAnswerForm(); submitForm.setAnswer("muc#roomconfig_publicroom", false); submitForm.setAnswer("muc#roomconfig_roomname", roomName); final List<String> owners = new ArrayList<String>(); owners.add(SparkManager.getSessionManager().getBareAddress()); submitForm.setAnswer("muc#roomconfig_roomowners", owners); multiUserChat.sendConfigurationForm(submitForm); } catch (XMPPException e1) { Log.error("Unable to send conference room chat configuration form.", e1); } ChatManager chatManager = SparkManager.getChatManager(); // Check if room already is open try { chatManager.getChatContainer().getChatRoom(room.getRoomname()); } catch (ChatRoomNotFoundException e) { chatManager.getChatContainer().addChatRoom(room); chatManager.getChatContainer().activateChatRoom(room); } for (String jid : jids) { multiUserChat.invite(jid, message); room.getTranscriptWindow().insertNotificationMessage(Res.getString("message.waiting.for.user.to.join",jid), ChatManager.NOTIFICATION_COLOR); } } /** * Returns an explanation for the exception. * * @param ex the <code>XMPPException</code> * @return the reason for the exception. */ public static String getReason(XMPPException ex) { String reason = ""; int code = 0; if (ex.getXMPPError() != null) { code = ex.getXMPPError().getCode(); } if (code == 0) { reason = "No response from server."; } else if (code == 401) { reason = "The password did not match the room's password."; } else if (code == 403) { reason = "You have been banned from this room."; } else if (code == 404) { reason = "The room you are trying to enter does not exist."; } else if (code == 405) { reason = "You do not have permission to create a room."; } else if (code == 407) { reason = "You are not a member of this room.\nThis room requires you to be a member to join."; } return reason; } /** * Enters a GroupChatRoom on the event thread. * * @param roomName the name of the room. * @param roomJID the rooms jid. * @param password the rooms password (if any). * @return the GroupChatRoom created. */ public static GroupChatRoom enterRoomOnSameThread(final String roomName, String roomJID, String password) { ChatManager chatManager = SparkManager.getChatManager(); final LocalPreferences pref = SettingsManager.getLocalPreferences(); final String nickname = pref.getNickname().trim(); try { GroupChatRoom chatRoom = (GroupChatRoom)chatManager.getChatContainer().getChatRoom(roomJID); MultiUserChat muc = chatRoom.getMultiUserChat(); if (!muc.isJoined()) { joinRoom(muc, nickname, password); } chatManager.getChatContainer().activateChatRoom(chatRoom); return chatRoom; } catch (ChatRoomNotFoundException e) { // Nothing to do } final MultiUserChat groupChat = new MultiUserChat(SparkManager.getConnection(), roomJID); final GroupChatRoom room = UIComponentRegistry.createGroupChatRoom(groupChat); room.setTabTitle(roomName); if (isPasswordRequired(roomJID) && password == null) { password = JOptionPane.showInputDialog(null, "Enter Room Password", "Need Password", JOptionPane.QUESTION_MESSAGE); if (!ModelUtil.hasLength(password)) { return null; } } final List<String> errors = new ArrayList<String>(); final String userPassword = password; if (!groupChat.isJoined()) { int groupChatCounter = 0; while (true) { groupChatCounter++; String joinName = nickname; if (groupChatCounter > 1) { joinName = joinName + groupChatCounter; } if (groupChatCounter < 10) { try { if (ModelUtil.hasLength(userPassword)) { groupChat.join(joinName, userPassword); } else { groupChat.join(joinName); } break; } catch (XMPPException ex) { int code = 0; if (ex.getXMPPError() != null) { code = ex.getXMPPError().getCode(); } if (code == 0) { errors.add("No response from server."); } else if (code == 401) { errors.add("The password did not match the room's password."); } else if (code == 403) { errors.add("You have been banned from this room."); } else if (code == 404) { errors.add("The room you are trying to enter does not exist."); } else if (code == 407) { errors.add("You are not a member of this room.\nThis room requires you to be a member to join."); } else if (code != 409) { break; } } } else { break; } } } if (errors.size() > 0) { String error = errors.get(0); JOptionPane.showMessageDialog(SparkManager.getMainWindow(), error, "Unable to join the room at this time.", JOptionPane.ERROR_MESSAGE); return null; } else if (groupChat.isJoined()) { chatManager.getChatContainer().addChatRoom(room); chatManager.getChatContainer().activateChatRoom(room); } else { JOptionPane.showMessageDialog(SparkManager.getMainWindow(), "Unable to join the room.", "Error", JOptionPane.ERROR_MESSAGE); return null; } return room; } public static void enterRoom(final MultiUserChat groupChat, String tabTitle, final String nickname, final String password) { final GroupChatRoom room = UIComponentRegistry.createGroupChatRoom(groupChat); room.setTabTitle(tabTitle); final List<String> errors = new ArrayList<String>(); if (!groupChat.isJoined()) { int groupChatCounter = 0; while (true) { groupChatCounter++; String joinName = nickname; if (groupChatCounter > 1) { joinName = joinName + groupChatCounter; } if (groupChatCounter < 10) { try { if (ModelUtil.hasLength(password)) { groupChat.join(joinName, password); } else { groupChat.join(joinName); } break; } catch (XMPPException ex) { int code = 0; if (ex.getXMPPError() != null) { code = ex.getXMPPError().getCode(); } if (code == 0) { errors.add("No response from server."); } else if (code == 401) { errors.add("A Password is required to enter this room."); } else if (code == 403) { errors.add("You have been banned from this room."); } else if (code == 404) { errors.add("The room you are trying to enter does not exist."); } else if (code == 407) { errors.add("You are not a member of this room.\nThis room requires you to be a member to join."); } else if (code != 409) { break; } } } else { break; } } } if (errors.size() > 0) { String error = errors.get(0); JOptionPane.showMessageDialog(SparkManager.getMainWindow(), error, "Could Not Join Room", JOptionPane.ERROR_MESSAGE); } else if (groupChat.isJoined()) { ChatManager chatManager = SparkManager.getChatManager(); chatManager.getChatContainer().addChatRoom(room); chatManager.getChatContainer().activateChatRoom(room); } else { JOptionPane.showMessageDialog(SparkManager.getMainWindow(), "Unable to join room.", "Error", JOptionPane.ERROR_MESSAGE); } } final static List<String> unclosableChatRooms = new ArrayList<String>(); public synchronized static void addUnclosableChatRoom(String jid) { unclosableChatRooms.add(jid); } public static boolean isChatRoomClosable(Component c) { if(c instanceof GroupChatRoom ) { GroupChatRoom groupChatRoom = (GroupChatRoom) c; String roomName = groupChatRoom.getChatRoom().getRoomname(); if(unclosableChatRooms.contains(roomName)){ return false; } } return true; } }