blob: 6c978a1d8dd046170f79aff437942ae93fb05f2a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.openmeetings.app.remote;
import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import org.apache.commons.collections.ComparatorUtils;
import org.openmeetings.app.conference.session.RoomClient;
import org.openmeetings.app.conference.whiteboard.Cliparts;
import org.openmeetings.app.conference.whiteboard.WhiteboardObject;
import org.openmeetings.app.conference.whiteboard.WhiteboardObjectList;
import org.openmeetings.app.conference.whiteboard.WhiteboardSyncLockObject;
import org.openmeetings.app.data.basic.AuthLevelmanagement;
import org.openmeetings.app.data.basic.Sessionmanagement;
import org.openmeetings.app.data.user.Usermanagement;
import org.openmeetings.app.remote.red5.ClientListManager;
import org.openmeetings.app.remote.red5.ScopeApplicationAdapter;
import org.openmeetings.app.remote.red5.WhiteBoardObjectListManager;
import org.openmeetings.app.remote.red5.WhiteBoardObjectListManagerById;
import org.red5.logging.Red5LoggerFactory;
import org.red5.server.api.IConnection;
import org.red5.server.api.Red5;
import org.red5.server.api.scope.IScope;
import org.red5.server.api.service.IPendingServiceCall;
import org.red5.server.api.service.IPendingServiceCallback;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
/**
*
* @author sebastianwagner
*
*/
public class WhiteBoardService implements IPendingServiceCallback {
private static final Logger log = Red5LoggerFactory.getLogger(
WhiteBoardService.class, "openmeetings");
@Autowired
private Usermanagement userManagement;
@Autowired
private final ScopeApplicationAdapter scopeApplicationAdapter = null;
@Autowired
private final ClientListManager clientListManager = null;
@Autowired
private final WhiteBoardObjectListManager whiteBoardObjectListManager = null;
@Autowired
private final WhiteBoardObjectListManagerById whiteBoardObjectListManagerById = null;
@Autowired
private Sessionmanagement sessionManagement;
@Autowired
private AuthLevelmanagement authLevelManagement;
/**
* Loading the List of Objects on the whiteboard
*
* @return HashMap<String,Map>
*/
public WhiteboardObject getRoomItems() {
try {
IConnection current = Red5.getConnectionLocal();
String streamid = current.getClient().getId();
RoomClient currentClient = this.clientListManager
.getClientByStreamId(streamid);
Long room_id = currentClient.getRoom_id();
log.debug("getRoomItems: " + room_id);
return this.whiteBoardObjectListManager
.getWhiteBoardObjectRoomId(room_id);
} catch (Exception err) {
log.error("[getRoomItems]", err);
}
return null;
}
public Long getNewWhiteboardId() {
try {
IConnection current = Red5.getConnectionLocal();
String streamid = current.getClient().getId();
RoomClient currentClient = this.clientListManager
.getClientByStreamId(streamid);
Long room_id = currentClient.getRoom_id();
Long whiteBoardId = this.whiteBoardObjectListManagerById
.getNewWhiteboardId(room_id);
return whiteBoardId;
} catch (Exception err) {
log.error("[deleteWhiteboard]", err);
}
return null;
}
public Boolean deleteWhiteboard(Long whiteBoardId) {
try {
IConnection current = Red5.getConnectionLocal();
String streamid = current.getClient().getId();
RoomClient currentClient = this.clientListManager
.getClientByStreamId(streamid);
Long room_id = currentClient.getRoom_id();
WhiteboardObjectList whiteboardObjectList = this.whiteBoardObjectListManagerById
.getWhiteBoardObjectListByRoomId(room_id);
for (Iterator<Long> iter = whiteboardObjectList
.getWhiteboardObjects().keySet().iterator(); iter.hasNext();) {
Long storedWhiteboardId = iter.next();
log.debug(" :: storedWhiteboardId :: " + storedWhiteboardId);
if (storedWhiteboardId.equals(whiteBoardId)) {
log.debug("Found Whiteboard to Remove");
}
}
Object returnValue = whiteboardObjectList.getWhiteboardObjects()
.remove(whiteBoardId);
log.debug(" :: whiteBoardId :: " + whiteBoardId);
this.whiteBoardObjectListManagerById
.setWhiteBoardObjectListRoomObj(room_id,
whiteboardObjectList);
if (returnValue != null) {
return true;
} else {
return false;
}
} catch (Exception err) {
log.error("[deleteWhiteboard]", err);
}
return null;
}
public WhiteboardObjectList getRoomItemsBy() {
try {
IConnection current = Red5.getConnectionLocal();
String streamid = current.getClient().getId();
RoomClient currentClient = this.clientListManager
.getClientByStreamId(streamid);
Long room_id = currentClient.getRoom_id();
log.debug("getRoomItems: " + room_id);
WhiteboardObjectList whiteboardObjectList = this.whiteBoardObjectListManagerById
.getWhiteBoardObjectListByRoomId(room_id);
if (whiteboardObjectList.getWhiteboardObjects().size() == 0) {
Long whiteBoardId = this.whiteBoardObjectListManagerById
.getNewWhiteboardId(room_id);
this.whiteBoardObjectListManagerById
.setWhiteBoardObjectListRoomObjAndWhiteboardId(room_id,
new WhiteboardObject(), whiteBoardId);
log.debug("Init New Room List");
whiteboardObjectList = this.whiteBoardObjectListManagerById
.getWhiteBoardObjectListByRoomId(room_id);
return whiteboardObjectList;
} else {
return whiteboardObjectList;
}
// return completeList;
} catch (Exception err) {
log.error("[getRoomItemsBy]", err);
}
return null;
}
/**
* change the draw status of a user, allow disallow him to draw anybody
* besides the Moderator to draw on the whiteboard, only a Moderator is
* allowed to trigger this function
*
* @param SID
* @param publicSID
* @param canDraw
* @return
*/
public Boolean setCanDraw(String SID, String publicSID, boolean canDraw) {
try {
IConnection current = Red5.getConnectionLocal();
String streamid = current.getClient().getId();
RoomClient currentClient = this.clientListManager
.getClientByStreamId(streamid);
Long users_id = sessionManagement.checkSession(SID);
Long user_level = userManagement.getUserLevelByID(users_id);
if (authLevelManagement.checkUserLevel(user_level)) {
if (currentClient.getIsMod()) {
RoomClient rcl = this.clientListManager
.getClientByPublicSID(publicSID, false);
if (rcl != null) {
rcl.setCanDraw(canDraw);
this.clientListManager.updateClientByStreamId(
rcl.getStreamid(), rcl);
HashMap<Integer, Object> newMessage = new HashMap<Integer, Object>();
newMessage.put(0, "updateDrawStatus");
newMessage.put(1, rcl);
this.scopeApplicationAdapter
.sendMessageWithClientWithSyncObject(newMessage, true);
} else {
return false;
}
} else {
return false;
}
}
} catch (Exception err) {
log.error("[setCanDraw]", err);
}
return null;
}
public Boolean setCanShare(String SID, String publicSID, boolean canShare) {
try {
IConnection current = Red5.getConnectionLocal();
String streamid = current.getClient().getId();
RoomClient currentClient = this.clientListManager
.getClientByStreamId(streamid);
Long users_id = sessionManagement.checkSession(SID);
Long user_level = userManagement.getUserLevelByID(users_id);
if (authLevelManagement.checkUserLevel(user_level)) {
if (currentClient.getIsMod()) {
RoomClient rcl = this.clientListManager
.getClientByPublicSID(publicSID, false);
if (rcl != null) {
rcl.setCanShare(canShare);
this.clientListManager.updateClientByStreamId(
rcl.getStreamid(), rcl);
HashMap<Integer, Object> newMessage = new HashMap<Integer, Object>();
newMessage.put(0, "updateDrawStatus");
newMessage.put(1, rcl);
this.scopeApplicationAdapter
.sendMessageWithClientWithSyncObject(newMessage, true);
} else {
return false;
}
} else {
return false;
}
}
} catch (Exception err) {
log.error("[setCanDraw]", err);
}
return null;
}
public Boolean setCanRemote(String SID, String publicSID, boolean canRemote) {
try {
IConnection current = Red5.getConnectionLocal();
String streamid = current.getClient().getId();
RoomClient currentClient = this.clientListManager
.getClientByStreamId(streamid);
Long users_id = sessionManagement.checkSession(SID);
Long user_level = userManagement.getUserLevelByID(users_id);
if (authLevelManagement.checkUserLevel(user_level)) {
if (currentClient.getIsMod()) {
RoomClient rcl = this.clientListManager
.getClientByPublicSID(publicSID, false);
if (rcl != null) {
rcl.setCanRemote(canRemote);
this.clientListManager.updateClientByStreamId(
rcl.getStreamid(), rcl);
HashMap<Integer, Object> newMessage = new HashMap<Integer, Object>();
newMessage.put(0, "updateDrawStatus");
newMessage.put(1, rcl);
this.scopeApplicationAdapter
.sendMessageWithClientWithSyncObject(newMessage, true);
} else {
return false;
}
} else {
return false;
}
}
} catch (Exception err) {
log.error("[setCanDraw]", err);
}
return null;
}
public Boolean setCanGiveAudio(String SID, String publicSID, boolean canGiveAudio) {
try {
log.debug("[setCanGiveAudio] " + SID + ", " + publicSID + ", " + canGiveAudio);
IConnection current = Red5.getConnectionLocal();
String streamid = current.getClient().getId();
RoomClient currentClient = this.clientListManager
.getClientByStreamId(streamid);
Long users_id = sessionManagement.checkSession(SID);
Long user_level = userManagement.getUserLevelByID(users_id);
if (authLevelManagement.checkUserLevel(user_level)) {
if (currentClient.getIsMod()) {
RoomClient rcl = this.clientListManager
.getClientByPublicSID(publicSID, false);
if (rcl != null) {
rcl.setCanGiveAudio(canGiveAudio);
this.clientListManager.updateClientByStreamId(
rcl.getStreamid(), rcl);
HashMap<Integer, Object> newMessage = new HashMap<Integer, Object>();
newMessage.put(0, "updateGiveAudioStatus");
newMessage.put(1, rcl);
this.scopeApplicationAdapter
.sendMessageWithClientWithSyncObject(newMessage, true);
} else {
return false;
}
} else {
return false;
}
}
} catch (Exception err) {
log.error("[setCanGiveAudio]", err);
}
return null;
}
public WhiteboardSyncLockObject startNewSyncprocess() {
try {
IConnection current = Red5.getConnectionLocal();
String streamid = current.getClient().getId();
RoomClient currentClient = this.clientListManager
.getClientByStreamId(streamid);
Long room_id = currentClient.getRoom_id();
WhiteboardSyncLockObject wSyncLockObject = new WhiteboardSyncLockObject();
wSyncLockObject.setAddtime(new Date());
wSyncLockObject.setPublicSID(currentClient.getPublicSID());
wSyncLockObject.setInitialLoaded(true);
Map<String, WhiteboardSyncLockObject> syncListRoom = this.whiteBoardObjectListManager
.getWhiteBoardSyncListByRoomid(room_id);
wSyncLockObject.setCurrentLoadingItem(true);
wSyncLockObject.setStarttime(new Date());
syncListRoom.put(currentClient.getPublicSID(), wSyncLockObject);
this.whiteBoardObjectListManager.setWhiteBoardSyncListByRoomid(
room_id, syncListRoom);
//Sync to clients
this.scopeApplicationAdapter.syncMessageToCurrentScope("sendSyncFlag", wSyncLockObject, true);
return wSyncLockObject;
} catch (Exception err) {
log.error("[startNewSyncprocess]", err);
}
return null;
}
public void sendCompletedSyncEvent() {
try {
IConnection current = Red5.getConnectionLocal();
String streamid = current.getClient().getId();
RoomClient currentClient = this.clientListManager
.getClientByStreamId(streamid);
Long room_id = currentClient.getRoom_id();
Map<String, WhiteboardSyncLockObject> syncListRoom = this.whiteBoardObjectListManager
.getWhiteBoardSyncListByRoomid(room_id);
WhiteboardSyncLockObject wSyncLockObject = syncListRoom
.get(currentClient.getPublicSID());
if (wSyncLockObject == null) {
log.error("WhiteboardSyncLockObject not found for this Client "
+ syncListRoom);
return;
} else if (!wSyncLockObject.isCurrentLoadingItem()) {
log.warn("WhiteboardSyncLockObject was not started yet "
+ syncListRoom);
return;
} else {
syncListRoom.remove(currentClient.getPublicSID());
this.whiteBoardObjectListManager.setWhiteBoardSyncListByRoomid(
room_id, syncListRoom);
int numberOfInitial = this
.getNumberOfInitialLoaders(syncListRoom);
if (numberOfInitial == 0) {
this.scopeApplicationAdapter.syncMessageToCurrentScope("sendSyncCompleteFlag", wSyncLockObject, true);
} else {
return;
}
}
} catch (Exception err) {
log.error("[sendCompletedSyncEvent]", err);
}
return;
}
private int getNumberOfInitialLoaders(
Map<String, WhiteboardSyncLockObject> syncListRoom)
throws Exception {
int number = 0;
for (Iterator<String> iter = syncListRoom.keySet().iterator(); iter
.hasNext();) {
WhiteboardSyncLockObject lockObject = syncListRoom.get(iter.next());
if (lockObject.isInitialLoaded()) {
number++;
}
}
return number;
}
/*
* Image Sync Sequence
*/
public void startNewObjectSyncProcess(String object_id, boolean isStarting) {
try {
log.debug("startNewObjectSyncprocess: " + object_id);
IConnection current = Red5.getConnectionLocal();
String streamid = current.getClient().getId();
RoomClient currentClient = this.clientListManager
.getClientByStreamId(streamid);
Long room_id = currentClient.getRoom_id();
WhiteboardSyncLockObject wSyncLockObject = new WhiteboardSyncLockObject();
wSyncLockObject.setAddtime(new Date());
wSyncLockObject.setPublicSID(currentClient.getPublicSID());
wSyncLockObject.setStarttime(new Date());
Map<String, WhiteboardSyncLockObject> syncListImage = this.whiteBoardObjectListManager
.getWhiteBoardObjectSyncListByRoomAndObjectId(room_id,
object_id);
syncListImage.put(currentClient.getPublicSID(), wSyncLockObject);
this.whiteBoardObjectListManager
.setWhiteBoardImagesSyncListByRoomAndObjectId(room_id,
object_id, syncListImage);
// Do only send the Token to show the Loading Splash for the
// initial-Request that starts the loading
if (isStarting) {
this.scopeApplicationAdapter.syncMessageToCurrentScope("sendObjectSyncFlag", wSyncLockObject, true);
}
} catch (Exception err) {
log.error("[startNewObjectSyncProcess]", err);
}
}
public int sendCompletedObjectSyncEvent(String object_id) {
try {
log.debug("sendCompletedObjectSyncEvent: " + object_id);
IConnection current = Red5.getConnectionLocal();
String streamid = current.getClient().getId();
RoomClient currentClient = this.clientListManager
.getClientByStreamId(streamid);
Long room_id = currentClient.getRoom_id();
Map<String, WhiteboardSyncLockObject> syncListImage = this.whiteBoardObjectListManager
.getWhiteBoardObjectSyncListByRoomAndObjectId(room_id,
object_id);
log.debug("sendCompletedObjectSyncEvent syncListImage: "
+ syncListImage);
WhiteboardSyncLockObject wSyncLockObject = syncListImage
.get(currentClient.getPublicSID());
if (wSyncLockObject == null) {
log.error("WhiteboardSyncLockObject not found for this Client "
+ currentClient.getPublicSID());
log.error("WhiteboardSyncLockObject not found for this syncListImage "
+ syncListImage);
return -2;
} else {
log.debug("sendCompletedImagesSyncEvent remove: "
+ currentClient.getPublicSID());
syncListImage.remove(currentClient.getPublicSID());
this.whiteBoardObjectListManager
.setWhiteBoardImagesSyncListByRoomAndObjectId(room_id,
object_id, syncListImage);
int numberOfInitial = this.whiteBoardObjectListManager
.getWhiteBoardObjectSyncListByRoomid(room_id).size();
log.debug("sendCompletedImagesSyncEvent numberOfInitial: "
+ numberOfInitial);
if (numberOfInitial == 0) {
return scopeApplicationAdapter.syncMessageToCurrentScope("sendObjectSyncCompleteFlag", wSyncLockObject, true);
} else {
return -4;
}
}
} catch (Exception err) {
log.error("[sendCompletedObjectSyncEvent]", err);
}
return -1;
}
public synchronized void removeUserFromAllLists(IScope scope,
RoomClient currentClient) {
try {
Long room_id = currentClient.getRoom_id();
// TODO: Maybe we should also check all rooms, independent from the
// current
// room_id if there is any user registered
if (room_id != null) {
log.debug("removeUserFromAllLists this.whiteBoardObjectListManager: "
+ this.whiteBoardObjectListManager);
log.debug("removeUserFromAllLists room_id: " + room_id);
// Check Initial Loaders
Map<String, WhiteboardSyncLockObject> syncListRoom = this.whiteBoardObjectListManager
.getWhiteBoardSyncListByRoomid(room_id);
WhiteboardSyncLockObject wSyncLockObject = syncListRoom
.get(currentClient.getPublicSID());
if (wSyncLockObject != null) {
syncListRoom.remove(currentClient.getPublicSID());
}
this.whiteBoardObjectListManager.setWhiteBoardSyncListByRoomid(
room_id, syncListRoom);
int numberOfInitial = this
.getNumberOfInitialLoaders(syncListRoom);
log.debug("scope " + scope);
if (numberOfInitial == 0 && scope != null) {
scopeApplicationAdapter.syncMessageToCurrentScope("sendSyncCompleteFlag", wSyncLockObject, false);
}
// Check Image Loaders
Map<String, Map<String, WhiteboardSyncLockObject>> syncListRoomImages = this.whiteBoardObjectListManager
.getWhiteBoardObjectSyncListByRoomid(room_id);
for (Iterator<String> iter = syncListRoomImages.keySet()
.iterator(); iter.hasNext();) {
String object_id = iter.next();
Map<String, WhiteboardSyncLockObject> syncListImages = syncListRoomImages
.get(object_id);
WhiteboardSyncLockObject wImagesSyncLockObject = syncListImages
.get(currentClient.getPublicSID());
if (wImagesSyncLockObject != null) {
syncListImages.remove(currentClient.getPublicSID());
}
this.whiteBoardObjectListManager
.setWhiteBoardImagesSyncListByRoomAndObjectId(
room_id, object_id, syncListImages);
}
int numberOfImageLoaders = this.whiteBoardObjectListManager
.getWhiteBoardObjectSyncListByRoomid(room_id).size();
if (numberOfImageLoaders == 0 && scope != null) {
scopeApplicationAdapter.syncMessageToCurrentScope("sendImagesSyncCompleteFlag", new Object[] { "remove" }, true);
}
}
} catch (Exception err) {
log.error("[removeUserFromAllLists]", err);
}
}
public Cliparts getClipArtIcons() {
try {
String current_dir = ScopeApplicationAdapter.webAppPath
+ File.separatorChar + "public" + File.separatorChar
+ "cliparts";
File clipart_dir = new File(current_dir);
FilenameFilter getFilesOnly = new FilenameFilter() {
public boolean accept(File b, String name) {
String absPath = b.getAbsolutePath() + File.separatorChar
+ name;
File f = new File(absPath);
return !f.isDirectory();
}
};
FilenameFilter getDirectoriesOnly = new FilenameFilter() {
public boolean accept(File b, String name) {
String absPath = b.getAbsolutePath() + File.separatorChar
+ name;
File f = new File(absPath);
return f.isDirectory() && !f.getName().equals("thumb");
}
};
Cliparts cl = new Cliparts();
cl.setFolderName("general");
String[] files_general = clipart_dir.list(getFilesOnly);
@SuppressWarnings("unchecked")
Comparator<String> comparator = ComparatorUtils.naturalComparator();
Arrays.sort(files_general, comparator);
cl.setGeneralList(files_general);
cl.setSubCategories(new LinkedList<Cliparts>());
for (File dir : clipart_dir.listFiles(getDirectoriesOnly)) {
Cliparts cl_sub = new Cliparts();
cl_sub.setFolderName("math");
String[] files = dir.list(getFilesOnly);
Arrays.sort(files, comparator);
cl_sub.setGeneralList(files);
cl.getSubCategories().add(cl_sub);
}
return cl;
} catch (Exception err) {
log.error("[getClipArtIcons]", err);
}
return null;
}
public void resultReceived(IPendingServiceCall arg0) {
// TODO Auto-generated method stub
log.debug("resultReceived: " + arg0);
}
}