/**
* 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) since 2004 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.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.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 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) {
InstantMessagingClient client = ClientManager.getInstance().getInstantMessagingClient(ureq.getIdentity().getName());
client.setGroupChatManager(new GroupChatManagerController(ureq, wControl));
return new InstantMessagingMainController(ureq, wControl);
}
/**
* @see org.olat.instantMessaging.InstantMessaging#getGroupChatManagerController()
*/
public GroupChatManagerController getGroupChatManagerController(UserRequest ureq) {
return ClientManager.getInstance().getInstantMessagingClient(ureq.getIdentity().getName()).getGroupChatManagerController();
}
/**
* @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) {
//add instanceID to ChatRoomString to distinguish between several OLAT-instances
String roomName = ores.getResourceableTypeName() + "-" + ores.getResourceableId();
return IMNameHelper.getGroupnameForOlatInstance(roomName);
}
}