| /* |
| * 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.apache.openmeetings.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.apache.openmeetings.data.basic.AuthLevelUtil; |
| import org.apache.openmeetings.data.basic.SessiondataDao; |
| import org.apache.openmeetings.data.user.UserManager; |
| import org.apache.openmeetings.data.whiteboard.WhiteBoardObjectListManagerById; |
| import org.apache.openmeetings.data.whiteboard.WhiteBoardObjectSyncManager; |
| import org.apache.openmeetings.data.whiteboard.dto.Cliparts; |
| import org.apache.openmeetings.data.whiteboard.dto.WhiteboardObject; |
| import org.apache.openmeetings.data.whiteboard.dto.WhiteboardObjectList; |
| import org.apache.openmeetings.data.whiteboard.dto.WhiteboardSyncLockObject; |
| import org.apache.openmeetings.persistence.beans.room.Client; |
| import org.apache.openmeetings.remote.red5.ScopeApplicationAdapter; |
| import org.apache.openmeetings.session.ISessionManager; |
| import org.apache.openmeetings.utils.OmFileHelper; |
| 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 UserManager userManager; |
| @Autowired |
| private final ScopeApplicationAdapter scopeApplicationAdapter = null; |
| @Autowired |
| private final ISessionManager sessionManager = null; |
| @Autowired |
| private final WhiteBoardObjectSyncManager whiteBoardObjectListManager = null; |
| @Autowired |
| private final WhiteBoardObjectListManagerById whiteBoardObjectListManagerById = null; |
| @Autowired |
| private SessiondataDao sessiondataDao; |
| @Autowired |
| private AuthLevelUtil authLevelUtil; |
| |
| public Long getNewWhiteboardId() { |
| try { |
| |
| IConnection current = Red5.getConnectionLocal(); |
| String streamid = current.getClient().getId(); |
| Client currentClient = this.sessionManager |
| .getClientByStreamId(streamid, null); |
| 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(); |
| Client currentClient = this.sessionManager |
| .getClientByStreamId(streamid, null); |
| 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(); |
| Client currentClient = this.sessionManager |
| .getClientByStreamId(streamid, null); |
| 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 null in case of success, false otherwise |
| */ |
| public Boolean setCanDraw(String SID, String publicSID, boolean canDraw) { |
| try { |
| |
| IConnection current = Red5.getConnectionLocal(); |
| String streamid = current.getClient().getId(); |
| Client currentClient = this.sessionManager |
| .getClientByStreamId(streamid, null); |
| |
| Long users_id = sessiondataDao.checkSession(SID); |
| Long user_level = userManager.getUserLevelByID(users_id); |
| |
| if (authLevelUtil.checkUserLevel(user_level)) { |
| |
| if (currentClient.getIsMod()) { |
| Client rcl = this.sessionManager |
| .getClientByPublicSID(publicSID, false, null); |
| |
| if (rcl != null) { |
| rcl.setCanDraw(canDraw); |
| this.sessionManager.updateClientByStreamId( |
| rcl.getStreamid(), rcl, false, null); |
| |
| 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(); |
| Client currentClient = this.sessionManager |
| .getClientByStreamId(streamid, null); |
| |
| Long users_id = sessiondataDao.checkSession(SID); |
| Long user_level = userManager.getUserLevelByID(users_id); |
| |
| if (authLevelUtil.checkUserLevel(user_level)) { |
| |
| if (currentClient.getIsMod()) { |
| Client rcl = this.sessionManager |
| .getClientByPublicSID(publicSID, false, null); |
| |
| if (rcl != null) { |
| rcl.setCanShare(canShare); |
| this.sessionManager.updateClientByStreamId( |
| rcl.getStreamid(), rcl, false, null); |
| |
| 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(); |
| Client currentClient = this.sessionManager |
| .getClientByStreamId(streamid, null); |
| |
| Long users_id = sessiondataDao.checkSession(SID); |
| Long user_level = userManager.getUserLevelByID(users_id); |
| |
| if (authLevelUtil.checkUserLevel(user_level)) { |
| |
| if (currentClient.getIsMod()) { |
| Client rcl = this.sessionManager |
| .getClientByPublicSID(publicSID, false, null); |
| |
| if (rcl != null) { |
| rcl.setCanRemote(canRemote); |
| this.sessionManager.updateClientByStreamId( |
| rcl.getStreamid(), rcl, false, null); |
| |
| 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(); |
| Client currentClient = this.sessionManager |
| .getClientByStreamId(streamid, null); |
| |
| Long users_id = sessiondataDao.checkSession(SID); |
| Long user_level = userManager.getUserLevelByID(users_id); |
| |
| if (authLevelUtil.checkUserLevel(user_level)) { |
| if (currentClient.getIsMod()) { |
| Client rcl = this.sessionManager |
| .getClientByPublicSID(publicSID, false, null); |
| |
| if (rcl != null) { |
| rcl.setCanGiveAudio(canGiveAudio); |
| this.sessionManager.updateClientByStreamId( |
| rcl.getStreamid(), rcl, false, null); |
| |
| 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(); |
| Client currentClient = this.sessionManager |
| .getClientByStreamId(streamid, null); |
| 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(); |
| Client currentClient = this.sessionManager |
| .getClientByStreamId(streamid, null); |
| 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(); |
| Client currentClient = this.sessionManager |
| .getClientByStreamId(streamid, null); |
| 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(); |
| Client currentClient = this.sessionManager |
| .getClientByStreamId(streamid, null); |
| 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) { |
| scopeApplicationAdapter.syncMessageToCurrentScope("sendObjectSyncCompleteFlag", wSyncLockObject, true); |
| return 1; |
| } else { |
| return -4; |
| } |
| } |
| |
| } catch (Exception err) { |
| log.error("[sendCompletedObjectSyncEvent]", err); |
| } |
| return -1; |
| } |
| |
| public synchronized void removeUserFromAllLists(IScope scope, |
| Client 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 { |
| File clipart_dir = OmFileHelper.getPublicClipartsDir(); |
| |
| FilenameFilter getFilesOnly = new FilenameFilter() { |
| public boolean accept(File b, String name) { |
| File f = new File(b, name); |
| return !f.isDirectory(); |
| } |
| }; |
| |
| FilenameFilter getDirectoriesOnly = new FilenameFilter() { |
| public boolean accept(File b, String name) { |
| File f = new File(b, name); |
| 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) { |
| log.debug("resultReceived: " + arg0); |
| } |
| } |