/** * OLAT - Online Learning and Training
* http://www.olat.org *

* 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. *

* Copyright (c) 1999-2006 at Multimedia- & E-Learning Services (MELS),
* University of Zurich, Switzerland. *

*/ package org.olat.instantMessaging; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.jivesoftware.smack.packet.Presence; import org.olat.basesecurity.Manager; import org.olat.basesecurity.ManagerFactory; import org.olat.basesecurity.SecurityGroup; import org.olat.core.commons.persistence.DBFactory; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.panel.Panel; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.core.id.Identity; import org.olat.core.id.OLATResourceable; import org.olat.core.id.Roles; import org.olat.core.logging.OLog; import org.olat.core.logging.Tracing; import org.olat.course.CourseFactory; import org.olat.course.CourseModule; import org.olat.course.ICourse; import org.olat.course.groupsandrights.CourseGroupManager; import org.olat.group.BusinessGroup; import org.olat.group.context.BGContextManager; import org.olat.group.context.BGContextManagerImpl; import org.olat.instantMessaging.groupchat.GroupChatManagerController; import org.olat.instantMessaging.groupchat.InstantMessagingGroupChatController; import org.olat.instantMessaging.rosterandchat.InstantMessagingMainController; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryManager; /** * * Implementation of the InstantMessaging Interface based on * the SMACK instant messaging library from jivesoftware.org * *

* Initial Date: 18.01.2005
* @author guido */ public class SmackInstantMessagingImpl implements InstantMessaging { private final InstantMessagingGroupSynchronisation buddyListSync = new SynchronizeBuddygroupsOverHTTP(); private Controller groupChatManagerController; private static OLog log = Tracing.createLoggerFor(SmackInstantMessagingImpl.class); /** * for clarity since needed for dynamic class loading */ public SmackInstantMessagingImpl() { super(); } /** * @see org.olat.instantMessaging.InstantMessaging#createClientController(org.olat.core.gui.UserRequest, * org.olat.core.gui.control.WindowControl) */ public Controller createClientController(UserRequest ureq, WindowControl wControl) { return new InstantMessagingMainController(ureq, wControl); } /** * @see org.olat.instantMessaging.InstantMessaging#createChatRoomLinkController(boolean, * java.lang.String, java.lang.String, org.olat.core.gui.UserRequest, * org.olat.core.gui.control.WindowControl, int) */ // public Controller createChatRoomLinkController(boolean passwordProtected, OLATResourceable ores, String chatRoomName, // UserRequest ureq, WindowControl wControl, Panel fixcsspanel, boolean compact, boolean anonymous) { // return new InstantMessagingGroupChatController(ureq, wControl, ores, createSaveChatRoomName(chatRoomName), fixcsspanel, compact, anonymous); // } public Controller getGroupChatManagerController(UserRequest ureq, WindowControl windowControl) { if (this.groupChatManagerController == null) { this.groupChatManagerController = new GroupChatManagerController(ureq, windowControl); return this.groupChatManagerController; } else { return this.groupChatManagerController; } } private String createSaveChatRoomName(String title) { if (title.contains("&")) { title = title.replaceAll("&", "&"); } return title; } /** * @see org.olat.instantMessaging.InstantMessaging#addUserToFriendsRoster(java.lang.String, * java.lang.String, java.lang.String, java.lang.String) * o_clusterok - nodes can access the IM server concurrently but only one thread should add a users to a group at * the same time. * Sync over whole clazz, not time critical as accessed by backgrounded threads */ public synchronized void addUserToFriendsRoster(Identity groupOwner, String groupId, String groupname, Identity addedIdentity) { // we have to make sure the user has an account on the instant messaging // server // by calling this it gets created if not yet exists. ClientManager.getInstance().getInstantMessagingCredentialForUser(addedIdentity.getName()); // we do not check whether a group already exists, we create it each time List list = new ArrayList(); list.add(groupOwner); buddyListSync.createSharedGroup(groupId, groupname, list); buddyListSync.addUserToSharedGroup(groupId, addedIdentity); if (log.isDebug()){ log.debug("Adding user to roster group::" + groupId + "username: " + addedIdentity.getName()); } } /** * @see org.olat.instantMessaging.InstantMessaging#removeUserFromFriendsRoster(java.lang.String, * java.lang.String) */ public void removeUserFromFriendsRoster(String groupId, String username) { buddyListSync.removeUserFromSharedGroup(groupId, username.toLowerCase()); if (log.isDebug()){ log.debug("Deleting user from roster group::" + groupId + "username: " + username); } } /** * @see org.olat.instantMessaging.InstantMessaging#deleteRosterGroup(java.lang.String) */ public void deleteRosterGroup(String groupId) { buddyListSync.deleteSharedGroup(groupId); if (log.isDebug()){ log.debug("Deleting roster group from instant messaging server::" + groupId); } } /** * @param groupId * @param displayName */ public void renameRosterGroup(String groupId, String displayName) { buddyListSync.renameSharedGroup(groupId, displayName); if (log.isDebug()){ log.debug("Renaming roster group on instant messaging server::" + groupId); } } /** * @see org.olat.instantMessaging.InstantMessaging#sendStatus(java.lang.String, * java.lang.String) */ public void sendStatus(String username, String message) { //only send status if client is active otherwise course dispose may recreate an connection if (ClientManager.getInstance().hasActiveInstantMessagingClient(username)) { InstantMessagingClient imc = ClientManager.getInstance().getInstantMessagingClient(username); String recentStatus = imc.getStatus(); //awareness presence packets get only sended if not "unavailable". Otherwise the unavailable status gets overwritten by an available one. if (!recentStatus.equals(InstantMessagingConstants.PRESENCE_MODE_UNAVAILABLE)) imc.sendPresence(Presence.Type.available, message, 0, Presence.Mode.valueOf(imc.getStatus())); } } /** * @see org.olat.instantMessaging.InstantMessaging#getIMPassword(java.lang.String) */ public String getIMPassword(String username) { return ClientManager.getInstance().getInstantMessagingClient(username).getPassword(); } /** * @return Set containing the usernames */ public Set getUsernamesFromConnectedUsers() { return ClientManager.getInstance().getUsernamesOfConnectedUsers(); } /** * @see org.olat.instantMessaging.InstantMessaging#getClients() */ public Map getClients() { return ClientManager.getInstance().getClients(); } /** * @see org.olat.instantMessaging.InstantMessaging#enableChat(java.lang.String) */ public void enableChat(String username) { ClientManager.getInstance().getInstantMessagingClient(username).enableCollaboration(); if (log.isDebug()){ log.debug("Enabling chat for user::" + username); } } /** * @param username * @param reason A resason why the chat is disabled like "Doing test" * @see org.olat.instantMessaging.InstantMessaging#disableChat(java.lang.String, * java.lang.String) */ public void disableChat(String username, String reason) { ClientManager.getInstance().getInstantMessagingClient(username).disableCollaboration(reason); if (log.isDebug()){ log.debug("Disabling chat for user::" + username + "and reason" + reason); } } /** * @see org.olat.instantMessaging.InstantMessaging#countConnectedUsers() */ public int countConnectedUsers() { return ClientManager.getInstance().countConnectedUsers(); } /** * @see org.olat.instantMessaging.InstantMessaging#synchonizeBuddyRoster(org.olat.group.BusinessGroup) */ public void synchonizeBuddyRoster(BusinessGroup group) { Manager securityManager = ManagerFactory.getManager(); SecurityGroup owners = group.getOwnerGroup(); SecurityGroup participants = group.getPartipiciantGroup(); List users = securityManager.getIdentitiesOfSecurityGroup(owners); users.addAll(securityManager.getIdentitiesOfSecurityGroup(participants)); for (Iterator iter = users.iterator(); iter.hasNext();) { Identity element = (Identity) iter.next(); // as jive only adds users to a group that already exist we have to make // sure they have an account. ClientManager.getInstance().getInstantMessagingCredentialForUser(element.getName()); } String groupId = InstantMessagingModule.getAdapter().createChatRoomString(group); if (users.size() > 0 ) { // only sync groups with users buddyListSync.createSharedGroup(groupId, group.getName(), users); if (log.isDebug()) log.debug("synchronizing group::" + group.toString()); } else { if (log.isDebug()) log.debug("empty group: not synchronizing group::" + group.toString()); } //when looping over all buddygroups and learninggroups close transaction after each group DBFactory.getInstance().commit(); DBFactory.getInstance().closeSession(); } /** * * @see org.olat.instantMessaging.InstantMessaging#synchronizeLearningGroupsWithIMServer() */ public void synchronizeLearningGroupsWithIMServer() { log.info("Starting synchronisation of LearningGroups with IM server"); RepositoryManager rm = RepositoryManager.getInstance(); BGContextManager contextManager = BGContextManagerImpl.getInstance(); //pull as admin Roles roles = new Roles(true, true, true, true, false); List allCourses = rm.queryByTypeLimitAccess(CourseModule.getCourseTypeName(), roles); int counter = 0; for (Iterator iterator = allCourses.iterator(); iterator.hasNext();) { RepositoryEntry entry = iterator.next(); ICourse course = CourseFactory.loadCourse(entry.getOlatResource()); CourseGroupManager groupManager = course.getCourseEnvironment().getCourseGroupManager(); List groups = groupManager.getAllLearningGroupsFromAllContexts(); for (Iterator iter = groups.iterator(); iter.hasNext();) { BusinessGroup group = iter.next(); synchonizeBuddyRoster(group); counter++; } } log.info("Ended synchronisation of LearningGroups with IM server: Synched "+counter+" groups"); } /** * Synchronize the groups with the IM system * To synchronize buddygroups, use the null-context. * Be aware that this action might take some time! * @param groupContext * @return true if successfull, false if IM server is not running */ public boolean synchronizeAllBuddyGroupsWithIMServer() { if (InstantMessagingModule.checkInstantMessagingServerRunning()) { log.info("Started synchronisation of BuddyGroups with IM server."); BGContextManager cm = BGContextManagerImpl.getInstance(); //null as argument pulls all buddygroups List groups = cm.getGroupsOfBGContext(null); int counter = 0; for (Iterator iter = groups.iterator(); iter.hasNext();) { BusinessGroup group = iter.next(); synchonizeBuddyRoster(group); counter++; } log.info("Ended synchronisation of BuddyGroups with IM server: Synched "+counter+" groups"); return true; } return false; } /** * @see org.olat.instantMessaging.InstantMessaging#createChatRoomString(org.olat.core.id.OLATResourceable */ public String createChatRoomString(OLATResourceable ores) { return ores.getResourceableTypeName() + "-" + ores.getResourceableId(); } }