http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8e63647c/openmeetings-core/src/main/java/org/apache/openmeetings/core/session/SessionManager.java
----------------------------------------------------------------------
diff --git 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/session/SessionManager.java
 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/session/SessionManager.java
index 8af1814..8e937d5 100644
--- 
a/openmeetings-core/src/main/java/org/apache/openmeetings/core/session/SessionManager.java
+++ 
b/openmeetings-core/src/main/java/org/apache/openmeetings/core/session/SessionManager.java
@@ -1,365 +1,365 @@
-/*
- * 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.core.session;
-
-import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Date;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.UUID;
-
-import org.apache.openmeetings.core.session.store.IClientPersistenceStore;
-import org.apache.openmeetings.db.dao.server.ISessionManager;
-import org.apache.openmeetings.db.dto.basic.SearchResult;
-import org.apache.openmeetings.db.dto.server.ClientSessionInfo;
-import org.apache.openmeetings.db.entity.room.StreamClient;
-import org.apache.openmeetings.db.entity.server.Server;
-import org.apache.wicket.util.string.Strings;
-import org.red5.logging.Red5LoggerFactory;
-import org.slf4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-
-/**
- * Handle {@link StreamClient} objects.
- *
- * Use a kind of decorator pattern to inject the {@link Server} into every 
call.
- *
- * @author sebawagner
- *
- */
-public class SessionManager implements ISessionManager {
-       protected static final Logger log = 
Red5LoggerFactory.getLogger(SessionManager.class, webAppRootKey);
-
-       @Autowired
-       private ServerUtil serverUtil;
-
-       /**
-        * Injected via Spring, needs a getter/setter because it can be 
configured
-        * Autowired will not suit here as there are multiple implementations 
of the
-        * {@link IClientPersistenceStore}
-        */
-       private IClientPersistenceStore cache;
-
-       public IClientPersistenceStore getCache() {
-               return cache;
-       }
-
-       public void setCache(IClientPersistenceStore cache) {
-               this.cache = cache;
-       }
-
-       @Override
-       public void clearCache() {
-               cache.clear();
-       }
-
-       @Override
-       public StreamClient add(StreamClient c, Server server) {
-               if (c == null) {
-                       return null;
-               }
-               if (server == null) {
-                       server = serverUtil.getCurrentServer();
-               }
-               c.setConnectedSince(new Date());
-               c.setRoomEnter(new Date());
-               if (Strings.isEmpty(c.getPublicSID())) {
-                       c.setPublicSID(UUID.randomUUID().toString());
-               }
-               c.setServer(server);
-
-               if (cache.containsKey(null, c.getStreamid())) {
-                       log.error("Tried to add an existing Client " + 
c.getStreamid());
-                       return null;
-               }
-
-               cache.put(c.getStreamid(), c);
-               return c;
-       }
-
-       @Override
-       public StreamClient addClientListItem(String streamId, String scopeName,
-                       int remotePort, String remoteAddress, String swfUrl, 
Server server) {
-               if (server == null) {
-                       server = serverUtil.getCurrentServer();
-               }
-               try {
-
-                       // Store the Connection into a bean and add it to the 
HashMap
-                       StreamClient rcm = new StreamClient();
-                       rcm.setConnectedSince(new Date());
-                       rcm.setStreamid(streamId);
-                       rcm.setScope(scopeName);
-                       rcm.setPublicSID(UUID.randomUUID().toString());
-                       rcm.setServer(server);
-                       rcm.setUserport(remotePort);
-                       rcm.setUserip(remoteAddress);
-                       rcm.setSwfurl(swfUrl);
-                       rcm.setIsMod(false);
-                       rcm.setCanDraw(false);
-
-                       if (cache.containsKey(null, streamId)) {
-                               log.error("Tried to add an existing Client " + 
streamId);
-                               return null;
-                       }
-
-                       cache.put(rcm.getStreamid(), rcm);
-
-                       return rcm;
-               } catch (Exception err) {
-                       log.error("[addClientListItem]", err);
-               }
-               return null;
-       }
-
-       @Override
-       public Collection<StreamClient> getClients() {
-               return cache.getClients();
-       }
-
-       @Override
-       public Collection<StreamClient> getClientsWithServer() {
-               return cache.getClientsWithServer();
-       }
-
-       @Override
-       public StreamClient getClientByStreamId(String streamId, Server server) 
{
-               if (server == null) {
-                       server = serverUtil.getCurrentServer();
-               }
-               try {
-                       if (!cache.containsKey(server, streamId)) {
-                               log.debug("Tried to get a non existing Client " 
+ streamId + " server " + server);
-                               return null;
-                       }
-                       return cache.get(server, streamId);
-               } catch (Exception err) {
-                       log.error("[getClientByStreamId]", err);
-               }
-               return null;
-       }
-
-       @Override
-       public StreamClient getClientByPublicSID(String publicSID, Server 
server) {
-               if (server == null) {
-                       server = serverUtil.getCurrentServer();
-               }
-               try {
-                       List<StreamClient> list = 
cache.getClientsByPublicSID(server, publicSID);
-                       return list == null || list.isEmpty() ? null : 
list.get(0);
-               } catch (Exception err) {
-                       log.error("[getClientByPublicSID]", err);
-               }
-               return null;
-       }
-
-       @Override
-       public ClientSessionInfo getClientByPublicSIDAnyServer(String 
publicSID) {
-               try {
-                       for (Entry<Long,List<StreamClient>> entry : 
cache.getClientsByPublicSID(publicSID).entrySet()) {
-                               for (StreamClient rcl : entry.getValue()) {
-                                       return new ClientSessionInfo(rcl, 
entry.getKey());
-                               }
-                       }
-               } catch (Exception err) {
-                       log.error("[getClientByPublicSIDAnyServer]", err);
-               }
-               return null;
-       }
-
-       @Override
-       public StreamClient getClientByUserId(Long userId) {
-               try {
-                       for (StreamClient rcl : cache.getClientsByUserId(null, 
userId)) {
-                               if (rcl.isScreenClient()) {
-                                       continue;
-                               }
-
-                               return rcl;
-                       }
-               } catch (Exception err) {
-                       log.error("[getClientByUserId]", err);
-               }
-               return null;
-       }
-
-       @Override
-       public boolean updateAVClientByStreamId(String streamId, StreamClient 
rcm, Server server) {
-               if (server == null) {
-                       server = serverUtil.getCurrentServer();
-               }
-               try {
-                       // get the corresponding user session object and update 
the settings
-                       StreamClient rclUsual = 
getClientByPublicSID(rcm.getPublicSID(), server);
-                       if (rclUsual != null) {
-                               rclUsual.setBroadCastId(rcm.getBroadCastId());
-                               rclUsual.setAvsettings(rcm.getAvsettings());
-                               rclUsual.setVHeight(rcm.getVHeight());
-                               rclUsual.setVWidth(rcm.getVWidth());
-                               rclUsual.setVX(rcm.getVX());
-                               rclUsual.setVY(rcm.getVY());
-                               StreamClient rclSaved = cache.get(server, 
rclUsual.getStreamid());
-                               if (rclSaved != null) {
-                                       cache.put(rclUsual.getStreamid(), 
rclUsual);
-                               } else {
-                                       log.debug("Tried to update a non 
existing Client " + rclUsual.getStreamid());
-                               }
-                       }
-
-                       updateClientByStreamId(streamId, rcm, false, server);
-                       return true;
-               } catch (Exception err) {
-                       log.error("[updateAVClientByStreamId]", err);
-               }
-               return false;
-       }
-
-       @Override
-       public boolean updateClientByStreamId(String streamId, StreamClient 
rcm, boolean updateRoomCount, Server server) {
-               if (server == null) {
-                       server = serverUtil.getCurrentServer();
-               }
-               try {
-                       StreamClient rclSaved = cache.get(server, streamId);
-
-                       if (rclSaved != null) {
-                               cache.put(streamId, rcm);
-                               return true;
-                       } else {
-                               log.debug("Tried to update a non existing 
Client " + streamId);
-                       }
-               } catch (Exception err) {
-                       log.error("[updateClientByStreamId]", err);
-               }
-               return false;
-       }
-
-       @Override
-       public boolean removeClient(String streamId, Server server) {
-               if (server == null) {
-                       server = serverUtil.getCurrentServer();
-               }
-               try {
-                       if (cache.containsKey(server,streamId)) {
-                               cache.remove(server,streamId);
-                               return true;
-                       } else {
-                               log.debug("Tried to remove a non existing 
Client " + streamId);
-                       }
-               } catch (Exception err) {
-                       log.error("[removeClient]", err);
-               }
-               return false;
-       }
-
-       @Override
-       public List<StreamClient> getClientListByRoom(Long roomId) {
-               List<StreamClient> roomClientList = new ArrayList<>();
-               try {
-                       for (StreamClient rcl : 
cache.getClientsByRoomId(roomId)) {
-                               if (rcl.isScreenClient()) {
-                                       continue;
-                               }
-
-                               // Only parse really those users out that are 
really a full session object
-                               // and no pseudo session object like the 
audio/video or screen
-                               // sharing connection
-                               roomClientList.add(rcl);
-                       }
-               } catch (Exception err) {
-                       log.error("[getClientListByRoom]", err);
-               }
-               return roomClientList;
-       }
-
-       @Override
-       public Collection<StreamClient> getClientListByRoomAll(Long roomId) {
-               try {
-                       return cache.getClientsByRoomId(roomId);
-               } catch (Exception err) {
-                       log.error("[getClientListByRoomAll]", err);
-               }
-               return null;
-       }
-
-       @Override
-       public List<StreamClient> getCurrentModeratorByRoom(Long roomId) {
-               List<StreamClient> rclList = new LinkedList<>();
-               List<StreamClient> currentClients = 
this.getClientListByRoom(roomId);
-               for (StreamClient rcl : currentClients) {
-                       if (rcl.getIsMod()) {
-                               rclList.add(rcl);
-                       }
-               }
-               return rclList;
-       }
-
-       @Override
-       public SearchResult<StreamClient> getListByStartAndMax(int start, int 
max, String orderby, boolean asc) {
-               SearchResult<StreamClient> sResult = new SearchResult<>();
-               sResult.setObjectName(StreamClient.class.getName());
-               sResult.setRecords(Long.valueOf(cache.size()));
-               sResult.setResult(cache.getClientsWithServer());
-               return sResult;
-       }
-
-       @Override
-       public long getRecordingCount(long roomId) {
-               List<StreamClient> currentClients = 
this.getClientListByRoom(roomId);
-               int numberOfRecordingUsers = 0;
-               for (StreamClient rcl : currentClients) {
-                       if (rcl.isStartRecording()) {
-                               numberOfRecordingUsers++;
-                       }
-               }
-               return numberOfRecordingUsers;
-       }
-
-       @Override
-       public long getPublishingCount(long roomId) {
-               List<StreamClient> currentClients = 
this.getClientListByRoom(roomId);
-               int numberOfPublishingUsers = 0;
-               for (StreamClient rcl : currentClients) {
-                       if (rcl.isStreamPublishStarted()) {
-                               numberOfPublishingUsers++;
-                       }
-               }
-               return numberOfPublishingUsers;
-       }
-
-       @Override
-       public List<Long> getActiveRoomIdsByServer(Server server) {
-               return cache.getRoomsIdsByServer(server == null ? 
serverUtil.getCurrentServer() : server);
-       }
-
-       @Override
-       public String getSessionStatistics() {
-               return 
cache.getDebugInformation(Arrays.asList(IClientPersistenceStore.DEBUG_DETAILS.SIZE));
-       }
-
-       @Override
-       public void sessionStart() {
-               // TODO Auto-generated method stub
-       }
-}
+/*
+ * 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.core.session;
+
+import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.UUID;
+
+import org.apache.openmeetings.core.session.store.IClientPersistenceStore;
+import org.apache.openmeetings.db.dao.server.ISessionManager;
+import org.apache.openmeetings.db.dto.basic.SearchResult;
+import org.apache.openmeetings.db.dto.server.ClientSessionInfo;
+import org.apache.openmeetings.db.entity.room.StreamClient;
+import org.apache.openmeetings.db.entity.server.Server;
+import org.apache.wicket.util.string.Strings;
+import org.red5.logging.Red5LoggerFactory;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * Handle {@link StreamClient} objects.
+ *
+ * Use a kind of decorator pattern to inject the {@link Server} into every 
call.
+ *
+ * @author sebawagner
+ *
+ */
+public class SessionManager implements ISessionManager {
+       protected static final Logger log = 
Red5LoggerFactory.getLogger(SessionManager.class, webAppRootKey);
+
+       @Autowired
+       private ServerUtil serverUtil;
+
+       /**
+        * Injected via Spring, needs a getter/setter because it can be 
configured
+        * Autowired will not suit here as there are multiple implementations 
of the
+        * {@link IClientPersistenceStore}
+        */
+       private IClientPersistenceStore cache;
+
+       public IClientPersistenceStore getCache() {
+               return cache;
+       }
+
+       public void setCache(IClientPersistenceStore cache) {
+               this.cache = cache;
+       }
+
+       @Override
+       public void clearCache() {
+               cache.clear();
+       }
+
+       @Override
+       public StreamClient add(StreamClient c, Server server) {
+               if (c == null) {
+                       return null;
+               }
+               if (server == null) {
+                       server = serverUtil.getCurrentServer();
+               }
+               c.setConnectedSince(new Date());
+               c.setRoomEnter(new Date());
+               if (Strings.isEmpty(c.getPublicSID())) {
+                       c.setPublicSID(UUID.randomUUID().toString());
+               }
+               c.setServer(server);
+
+               if (cache.containsKey(null, c.getStreamid())) {
+                       log.error("Tried to add an existing Client " + 
c.getStreamid());
+                       return null;
+               }
+
+               cache.put(c.getStreamid(), c);
+               return c;
+       }
+
+       @Override
+       public StreamClient addClientListItem(String streamId, String scopeName,
+                       int remotePort, String remoteAddress, String swfUrl, 
Server server) {
+               if (server == null) {
+                       server = serverUtil.getCurrentServer();
+               }
+               try {
+
+                       // Store the Connection into a bean and add it to the 
HashMap
+                       StreamClient rcm = new StreamClient();
+                       rcm.setConnectedSince(new Date());
+                       rcm.setStreamid(streamId);
+                       rcm.setScope(scopeName);
+                       rcm.setPublicSID(UUID.randomUUID().toString());
+                       rcm.setServer(server);
+                       rcm.setUserport(remotePort);
+                       rcm.setUserip(remoteAddress);
+                       rcm.setSwfurl(swfUrl);
+                       rcm.setIsMod(false);
+                       rcm.setCanDraw(false);
+
+                       if (cache.containsKey(null, streamId)) {
+                               log.error("Tried to add an existing Client " + 
streamId);
+                               return null;
+                       }
+
+                       cache.put(rcm.getStreamid(), rcm);
+
+                       return rcm;
+               } catch (Exception err) {
+                       log.error("[addClientListItem]", err);
+               }
+               return null;
+       }
+
+       @Override
+       public Collection<StreamClient> getClients() {
+               return cache.getClients();
+       }
+
+       @Override
+       public Collection<StreamClient> getClientsWithServer() {
+               return cache.getClientsWithServer();
+       }
+
+       @Override
+       public StreamClient getClientByStreamId(String streamId, Server server) 
{
+               if (server == null) {
+                       server = serverUtil.getCurrentServer();
+               }
+               try {
+                       if (!cache.containsKey(server, streamId)) {
+                               log.debug("Tried to get a non existing Client " 
+ streamId + " server " + server);
+                               return null;
+                       }
+                       return cache.get(server, streamId);
+               } catch (Exception err) {
+                       log.error("[getClientByStreamId]", err);
+               }
+               return null;
+       }
+
+       @Override
+       public StreamClient getClientByPublicSID(String publicSID, Server 
server) {
+               if (server == null) {
+                       server = serverUtil.getCurrentServer();
+               }
+               try {
+                       List<StreamClient> list = 
cache.getClientsByPublicSID(server, publicSID);
+                       return list == null || list.isEmpty() ? null : 
list.get(0);
+               } catch (Exception err) {
+                       log.error("[getClientByPublicSID]", err);
+               }
+               return null;
+       }
+
+       @Override
+       public ClientSessionInfo getClientByPublicSIDAnyServer(String 
publicSID) {
+               try {
+                       for (Entry<Long,List<StreamClient>> entry : 
cache.getClientsByPublicSID(publicSID).entrySet()) {
+                               for (StreamClient rcl : entry.getValue()) {
+                                       return new ClientSessionInfo(rcl, 
entry.getKey());
+                               }
+                       }
+               } catch (Exception err) {
+                       log.error("[getClientByPublicSIDAnyServer]", err);
+               }
+               return null;
+       }
+
+       @Override
+       public StreamClient getClientByUserId(Long userId) {
+               try {
+                       for (StreamClient rcl : cache.getClientsByUserId(null, 
userId)) {
+                               if (rcl.isScreenClient()) {
+                                       continue;
+                               }
+
+                               return rcl;
+                       }
+               } catch (Exception err) {
+                       log.error("[getClientByUserId]", err);
+               }
+               return null;
+       }
+
+       @Override
+       public boolean updateAVClientByStreamId(String streamId, StreamClient 
rcm, Server server) {
+               if (server == null) {
+                       server = serverUtil.getCurrentServer();
+               }
+               try {
+                       // get the corresponding user session object and update 
the settings
+                       StreamClient rclUsual = 
getClientByPublicSID(rcm.getPublicSID(), server);
+                       if (rclUsual != null) {
+                               rclUsual.setBroadCastId(rcm.getBroadCastId());
+                               rclUsual.setAvsettings(rcm.getAvsettings());
+                               rclUsual.setVHeight(rcm.getVHeight());
+                               rclUsual.setVWidth(rcm.getVWidth());
+                               rclUsual.setVX(rcm.getVX());
+                               rclUsual.setVY(rcm.getVY());
+                               StreamClient rclSaved = cache.get(server, 
rclUsual.getStreamid());
+                               if (rclSaved != null) {
+                                       cache.put(rclUsual.getStreamid(), 
rclUsual);
+                               } else {
+                                       log.debug("Tried to update a non 
existing Client " + rclUsual.getStreamid());
+                               }
+                       }
+
+                       updateClientByStreamId(streamId, rcm, false, server);
+                       return true;
+               } catch (Exception err) {
+                       log.error("[updateAVClientByStreamId]", err);
+               }
+               return false;
+       }
+
+       @Override
+       public boolean updateClientByStreamId(String streamId, StreamClient 
rcm, boolean updateRoomCount, Server server) {
+               if (server == null) {
+                       server = serverUtil.getCurrentServer();
+               }
+               try {
+                       StreamClient rclSaved = cache.get(server, streamId);
+
+                       if (rclSaved != null) {
+                               cache.put(streamId, rcm);
+                               return true;
+                       } else {
+                               log.debug("Tried to update a non existing 
Client " + streamId);
+                       }
+               } catch (Exception err) {
+                       log.error("[updateClientByStreamId]", err);
+               }
+               return false;
+       }
+
+       @Override
+       public boolean removeClient(String streamId, Server server) {
+               if (server == null) {
+                       server = serverUtil.getCurrentServer();
+               }
+               try {
+                       if (cache.containsKey(server,streamId)) {
+                               cache.remove(server,streamId);
+                               return true;
+                       } else {
+                               log.debug("Tried to remove a non existing 
Client " + streamId);
+                       }
+               } catch (Exception err) {
+                       log.error("[removeClient]", err);
+               }
+               return false;
+       }
+
+       @Override
+       public List<StreamClient> getClientListByRoom(Long roomId) {
+               List<StreamClient> roomClientList = new ArrayList<>();
+               try {
+                       for (StreamClient rcl : 
cache.getClientsByRoomId(roomId)) {
+                               if (rcl.isScreenClient()) {
+                                       continue;
+                               }
+
+                               // Only parse really those users out that are 
really a full session object
+                               // and no pseudo session object like the 
audio/video or screen
+                               // sharing connection
+                               roomClientList.add(rcl);
+                       }
+               } catch (Exception err) {
+                       log.error("[getClientListByRoom]", err);
+               }
+               return roomClientList;
+       }
+
+       @Override
+       public Collection<StreamClient> getClientListByRoomAll(Long roomId) {
+               try {
+                       return cache.getClientsByRoomId(roomId);
+               } catch (Exception err) {
+                       log.error("[getClientListByRoomAll]", err);
+               }
+               return null;
+       }
+
+       @Override
+       public List<StreamClient> getCurrentModeratorByRoom(Long roomId) {
+               List<StreamClient> rclList = new LinkedList<>();
+               List<StreamClient> currentClients = 
this.getClientListByRoom(roomId);
+               for (StreamClient rcl : currentClients) {
+                       if (rcl.getIsMod()) {
+                               rclList.add(rcl);
+                       }
+               }
+               return rclList;
+       }
+
+       @Override
+       public SearchResult<StreamClient> getListByStartAndMax(int start, int 
max, String orderby, boolean asc) {
+               SearchResult<StreamClient> sResult = new SearchResult<>();
+               sResult.setObjectName(StreamClient.class.getName());
+               sResult.setRecords(Long.valueOf(cache.size()));
+               sResult.setResult(cache.getClientsWithServer());
+               return sResult;
+       }
+
+       @Override
+       public long getRecordingCount(long roomId) {
+               List<StreamClient> currentClients = 
this.getClientListByRoom(roomId);
+               int numberOfRecordingUsers = 0;
+               for (StreamClient rcl : currentClients) {
+                       if (rcl.isStartRecording()) {
+                               numberOfRecordingUsers++;
+                       }
+               }
+               return numberOfRecordingUsers;
+       }
+
+       @Override
+       public long getPublishingCount(long roomId) {
+               List<StreamClient> currentClients = 
this.getClientListByRoom(roomId);
+               int numberOfPublishingUsers = 0;
+               for (StreamClient rcl : currentClients) {
+                       if (rcl.isStreamPublishStarted()) {
+                               numberOfPublishingUsers++;
+                       }
+               }
+               return numberOfPublishingUsers;
+       }
+
+       @Override
+       public List<Long> getActiveRoomIdsByServer(Server server) {
+               return cache.getRoomsIdsByServer(server == null ? 
serverUtil.getCurrentServer() : server);
+       }
+
+       @Override
+       public String getSessionStatistics() {
+               return 
cache.getDebugInformation(Arrays.asList(IClientPersistenceStore.DEBUG_DETAILS.SIZE));
+       }
+
+       @Override
+       public void sessionStart() {
+               // TODO Auto-generated method stub
+       }
+}

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8e63647c/openmeetings-core/src/site/site.xml
----------------------------------------------------------------------
diff --git a/openmeetings-core/src/site/site.xml 
b/openmeetings-core/src/site/site.xml
index c26954e..0d9f35c 100644
--- a/openmeetings-core/src/site/site.xml
+++ b/openmeetings-core/src/site/site.xml
@@ -1,40 +1,40 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-   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.
- -->
-<project xmlns="http://maven.apache.org/DECORATION/1.7.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
-  xsi:schemaLocation="http://maven.apache.org/DECORATION/1.7.0 
http://maven.apache.org/xsd/decoration-1.7.0.xsd";
-  name="Apache OpenMeetings Project">
-
-       <body>
-               <menu ref="parent"/>
-               <menu name="Project">
-                       <item name="About" href="/index.html" />
-                       <item name="Info" href="/project-info.html" />
-                       <item name="Summary" href="/project-summary.html" />
-                       <item name="License" href="/license.html" />
-                       <item name="Dependencies" href="/dependencies.html" />
-                       <item name="Dependency Convergence" 
href="/dependency-convergence.html" />
-                       <item name="RAT Report" href="/rat-report.html" />
-                       <item name="JavaDoc" href="/apidocs/index.html" 
target="_blank" />
-               </menu>
-       </body>
-       <custom>
-               <reflowSkin>
-                       <bottomNav maxSpan="12">
-                               <column>Parent Project</column>
-                               <column>Project</column>
-                       </bottomNav>
-               </reflowSkin>
-       </custom>
-</project>
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   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.
+ -->
+<project xmlns="http://maven.apache.org/DECORATION/1.7.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+  xsi:schemaLocation="http://maven.apache.org/DECORATION/1.7.0 
http://maven.apache.org/xsd/decoration-1.7.0.xsd";
+  name="Apache OpenMeetings Project">
+
+       <body>
+               <menu ref="parent"/>
+               <menu name="Project">
+                       <item name="About" href="/index.html" />
+                       <item name="Info" href="/project-info.html" />
+                       <item name="Summary" href="/project-summary.html" />
+                       <item name="License" href="/license.html" />
+                       <item name="Dependencies" href="/dependencies.html" />
+                       <item name="Dependency Convergence" 
href="/dependency-convergence.html" />
+                       <item name="RAT Report" href="/rat-report.html" />
+                       <item name="JavaDoc" href="/apidocs/index.html" 
target="_blank" />
+               </menu>
+       </body>
+       <custom>
+               <reflowSkin>
+                       <bottomNav maxSpan="12">
+                               <column>Parent Project</column>
+                               <column>Project</column>
+                       </bottomNav>
+               </reflowSkin>
+       </custom>
+</project>

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8e63647c/openmeetings-core/src/test/java/org/apache/openmeetings/test/rtmp/LoadTestRtmpClient.java
----------------------------------------------------------------------
diff --git 
a/openmeetings-core/src/test/java/org/apache/openmeetings/test/rtmp/LoadTestRtmpClient.java
 
b/openmeetings-core/src/test/java/org/apache/openmeetings/test/rtmp/LoadTestRtmpClient.java
index 4247263..3a2a886 100644
--- 
a/openmeetings-core/src/test/java/org/apache/openmeetings/test/rtmp/LoadTestRtmpClient.java
+++ 
b/openmeetings-core/src/test/java/org/apache/openmeetings/test/rtmp/LoadTestRtmpClient.java
@@ -1,172 +1,172 @@
-/*
- * 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.test.rtmp;
-
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.red5.client.net.rtmp.ClientExceptionHandler;
-import org.red5.client.net.rtmp.INetStreamEventHandler;
-import org.red5.client.net.rtmp.RTMPClient;
-import org.red5.server.api.service.IPendingServiceCall;
-import org.red5.server.api.service.IPendingServiceCallback;
-import org.red5.server.net.rtmp.event.Notify;
-
-public class LoadTestRtmpClient extends RTMPClient implements 
IPendingServiceCallback, INetStreamEventHandler, ClientExceptionHandler {
-
-       private class CallObject {
-               Date started;
-               Date ended;
-
-               public CallObject(Date started) {
-                       super();
-                       this.started = started;
-               }
-
-               public Date getStarted() {
-                       return started;
-               }
-
-               public Date getEnded() {
-                       return ended;
-               }
-
-               public void setEnded(Date ended) {
-                       this.ended = ended;
-               }
-       }
-
-       private int counterCalls = 0; // a call is always 2 steps
-       private Map<Integer, CallObject> calls = new HashMap<>();
-       private boolean isConnected = false;
-       private final int instanceId;
-
-       public LoadTestRtmpClient(int instanceId) {
-               this.instanceId = instanceId;
-       }
-
-       public boolean performCall() {
-
-               // System.err.println("performCall " + isConnected);
-
-               if (!isConnected) {
-                       return false;
-               }
-
-               if (counterCalls % 2 == 0) {
-
-                       if (counterCalls > 10) {
-
-                               return true;
-
-                       }
-
-                       System.err.println("Rest o do new call " + 
counterCalls);
-                       counterCalls++;
-
-                       Map<String, Integer> map = new HashMap<>();
-                       map.put("instanceId", instanceId);
-                       map.put("count", counterCalls);
-                       calls.put(counterCalls, new CallObject(new Date()));
-                       invoke("loadTestSyncMessage", new Object[] 
{"syncMessageToCurrentScopeResult", map, true }, this);
-
-               } else {
-                       System.err.println("Call running " + counterCalls);
-               }
-
-
-
-               return false;
-       }
-
-       public double getAverageTime() {
-               long overallTime = 0L;
-
-               for (Entry<Integer, CallObject> tCallObjectEntry : 
calls.entrySet()) {
-
-                       long deltaTime = 
tCallObjectEntry.getValue().getEnded().getTime()
-                                       - 
tCallObjectEntry.getValue().getStarted().getTime();
-
-                       // System.err.println("Key " + tCallObjectEntry.getKey()
-                       // + "deltaTime " + deltaTime);
-
-                       overallTime += deltaTime;
-
-               }
-
-               double averageTime = Long.valueOf(overallTime).doubleValue()
-                               / Integer.valueOf(calls.size()).doubleValue();
-
-               return averageTime;
-       }
-
-       @Override
-       public void resultReceived(IPendingServiceCall call) {
-               String method = call == null ? null : 
call.getServiceMethodName();
-               System.err.println("method "+method);
-               if (method == null) {
-                       return;
-               }
-               if ("connect".equals(method)) {
-                       isConnected = true;
-               }
-
-               if ("loadTestSyncMessage".equals(method)) {
-
-                       CallObject tCallObject = calls.get(counterCalls);
-                       if (tCallObject == null) {
-
-                               for (Entry<Integer, CallObject> 
tCallObjectEntry : calls.entrySet()) {
-
-                                       System.err.println("Key " + 
tCallObjectEntry.getKey()
-                                                       + "tCallObjectEntry "
-                                                       + 
tCallObjectEntry.getValue().getStarted());
-
-                               }
-
-                               throw new RuntimeException(
-                                               "tCallObject is null 
currentCountReturn "
-                                                               + counterCalls 
+ " list size "
-                                                               + calls.size());
-                       }
-                       tCallObject.setEnded(new Date());
-                       calls.put(counterCalls, tCallObject);
-
-                       System.err.println("Call received " + counterCalls
-                                       + " instanceId: " + instanceId);
-
-                       counterCalls++;
-               }
-
-       }
-
-
-       @Override
-       public void onStreamEvent(Notify notify) {
-               // TODO Auto-generated method stub
-
-       }
-
-       public int getNumberOfCalls() {
-               return calls.size();
-       }
-
-}
+/*
+ * 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.test.rtmp;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.red5.client.net.rtmp.ClientExceptionHandler;
+import org.red5.client.net.rtmp.INetStreamEventHandler;
+import org.red5.client.net.rtmp.RTMPClient;
+import org.red5.server.api.service.IPendingServiceCall;
+import org.red5.server.api.service.IPendingServiceCallback;
+import org.red5.server.net.rtmp.event.Notify;
+
+public class LoadTestRtmpClient extends RTMPClient implements 
IPendingServiceCallback, INetStreamEventHandler, ClientExceptionHandler {
+
+       private class CallObject {
+               Date started;
+               Date ended;
+
+               public CallObject(Date started) {
+                       super();
+                       this.started = started;
+               }
+
+               public Date getStarted() {
+                       return started;
+               }
+
+               public Date getEnded() {
+                       return ended;
+               }
+
+               public void setEnded(Date ended) {
+                       this.ended = ended;
+               }
+       }
+
+       private int counterCalls = 0; // a call is always 2 steps
+       private Map<Integer, CallObject> calls = new HashMap<>();
+       private boolean isConnected = false;
+       private final int instanceId;
+
+       public LoadTestRtmpClient(int instanceId) {
+               this.instanceId = instanceId;
+       }
+
+       public boolean performCall() {
+
+               // System.err.println("performCall " + isConnected);
+
+               if (!isConnected) {
+                       return false;
+               }
+
+               if (counterCalls % 2 == 0) {
+
+                       if (counterCalls > 10) {
+
+                               return true;
+
+                       }
+
+                       System.err.println("Rest o do new call " + 
counterCalls);
+                       counterCalls++;
+
+                       Map<String, Integer> map = new HashMap<>();
+                       map.put("instanceId", instanceId);
+                       map.put("count", counterCalls);
+                       calls.put(counterCalls, new CallObject(new Date()));
+                       invoke("loadTestSyncMessage", new Object[] 
{"syncMessageToCurrentScopeResult", map, true }, this);
+
+               } else {
+                       System.err.println("Call running " + counterCalls);
+               }
+
+
+
+               return false;
+       }
+
+       public double getAverageTime() {
+               long overallTime = 0L;
+
+               for (Entry<Integer, CallObject> tCallObjectEntry : 
calls.entrySet()) {
+
+                       long deltaTime = 
tCallObjectEntry.getValue().getEnded().getTime()
+                                       - 
tCallObjectEntry.getValue().getStarted().getTime();
+
+                       // System.err.println("Key " + tCallObjectEntry.getKey()
+                       // + "deltaTime " + deltaTime);
+
+                       overallTime += deltaTime;
+
+               }
+
+               double averageTime = Long.valueOf(overallTime).doubleValue()
+                               / Integer.valueOf(calls.size()).doubleValue();
+
+               return averageTime;
+       }
+
+       @Override
+       public void resultReceived(IPendingServiceCall call) {
+               String method = call == null ? null : 
call.getServiceMethodName();
+               System.err.println("method "+method);
+               if (method == null) {
+                       return;
+               }
+               if ("connect".equals(method)) {
+                       isConnected = true;
+               }
+
+               if ("loadTestSyncMessage".equals(method)) {
+
+                       CallObject tCallObject = calls.get(counterCalls);
+                       if (tCallObject == null) {
+
+                               for (Entry<Integer, CallObject> 
tCallObjectEntry : calls.entrySet()) {
+
+                                       System.err.println("Key " + 
tCallObjectEntry.getKey()
+                                                       + "tCallObjectEntry "
+                                                       + 
tCallObjectEntry.getValue().getStarted());
+
+                               }
+
+                               throw new RuntimeException(
+                                               "tCallObject is null 
currentCountReturn "
+                                                               + counterCalls 
+ " list size "
+                                                               + calls.size());
+                       }
+                       tCallObject.setEnded(new Date());
+                       calls.put(counterCalls, tCallObject);
+
+                       System.err.println("Call received " + counterCalls
+                                       + " instanceId: " + instanceId);
+
+                       counterCalls++;
+               }
+
+       }
+
+
+       @Override
+       public void onStreamEvent(Notify notify) {
+               // TODO Auto-generated method stub
+
+       }
+
+       public int getNumberOfCalls() {
+               return calls.size();
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8e63647c/openmeetings-core/src/test/java/org/apache/openmeetings/test/rtmp/SimulateLoad.java
----------------------------------------------------------------------
diff --git 
a/openmeetings-core/src/test/java/org/apache/openmeetings/test/rtmp/SimulateLoad.java
 
b/openmeetings-core/src/test/java/org/apache/openmeetings/test/rtmp/SimulateLoad.java
index fd95155..b68aa0f 100644
--- 
a/openmeetings-core/src/test/java/org/apache/openmeetings/test/rtmp/SimulateLoad.java
+++ 
b/openmeetings-core/src/test/java/org/apache/openmeetings/test/rtmp/SimulateLoad.java
@@ -1,92 +1,92 @@
-/*
- * 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.test.rtmp;
-
-import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey;
-
-import org.red5.logging.Red5LoggerFactory;
-import org.slf4j.Logger;
-
-public class SimulateLoad extends Thread {
-       private static final Logger log = 
Red5LoggerFactory.getLogger(SimulateLoad.class, webAppRootKey);
-
-       private LoadTestRtmpClient loadTestRtmpClient;
-       private boolean testRunning = true;
-
-       public double getAverageTime() {
-               return loadTestRtmpClient.getAverageTime();
-       }
-
-       public boolean isTestRunning() {
-               return testRunning;
-       }
-
-       public static void main(String... args) {
-               try {
-                       if (args.length != 4) {
-                               throw new RuntimeException("4 args needed, 
host, port, context, instanceId");
-                       }
-                       for (String arg : args) {
-                               System.err.println("arg: " + arg);
-                       }
-                       SimulateLoad simulateLoad = new SimulateLoad(args[0], 
Integer
-                                       .valueOf(args[1]).intValue(), args[2], 
Integer.valueOf(
-                                       args[3]).intValue());
-                       simulateLoad.start();
-                       System.err.println("started ");
-
-               } catch (Exception er) {
-                       log.error("Error", er);
-               }
-       }
-
-       public SimulateLoad(String host, int port, String applicationContext,
-                       int instanceId) {
-               super();
-
-               loadTestRtmpClient = new LoadTestRtmpClient(instanceId);
-               loadTestRtmpClient.connect(host, port, applicationContext,
-                               loadTestRtmpClient);
-       }
-
-       @Override
-       public void run() {
-               try {
-
-                       System.err.println("######### start client");
-
-                       while (testRunning) {
-                               testRunning = !loadTestRtmpClient.performCall();
-                               try {
-                                       Thread.sleep(200);
-                               } catch (InterruptedException e) {
-                                       log.error("Error", e);
-                               }
-                       }
-
-               } catch (Exception e) {
-                       log.error("Error", e);
-               }
-       }
-
-       public int getNumberOfCalls() {
-               return loadTestRtmpClient.getNumberOfCalls();
-       }
-
-}
+/*
+ * 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.test.rtmp;
+
+import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey;
+
+import org.red5.logging.Red5LoggerFactory;
+import org.slf4j.Logger;
+
+public class SimulateLoad extends Thread {
+       private static final Logger log = 
Red5LoggerFactory.getLogger(SimulateLoad.class, webAppRootKey);
+
+       private LoadTestRtmpClient loadTestRtmpClient;
+       private boolean testRunning = true;
+
+       public double getAverageTime() {
+               return loadTestRtmpClient.getAverageTime();
+       }
+
+       public boolean isTestRunning() {
+               return testRunning;
+       }
+
+       public static void main(String... args) {
+               try {
+                       if (args.length != 4) {
+                               throw new RuntimeException("4 args needed, 
host, port, context, instanceId");
+                       }
+                       for (String arg : args) {
+                               System.err.println("arg: " + arg);
+                       }
+                       SimulateLoad simulateLoad = new SimulateLoad(args[0], 
Integer
+                                       .valueOf(args[1]).intValue(), args[2], 
Integer.valueOf(
+                                       args[3]).intValue());
+                       simulateLoad.start();
+                       System.err.println("started ");
+
+               } catch (Exception er) {
+                       log.error("Error", er);
+               }
+       }
+
+       public SimulateLoad(String host, int port, String applicationContext,
+                       int instanceId) {
+               super();
+
+               loadTestRtmpClient = new LoadTestRtmpClient(instanceId);
+               loadTestRtmpClient.connect(host, port, applicationContext,
+                               loadTestRtmpClient);
+       }
+
+       @Override
+       public void run() {
+               try {
+
+                       System.err.println("######### start client");
+
+                       while (testRunning) {
+                               testRunning = !loadTestRtmpClient.performCall();
+                               try {
+                                       Thread.sleep(200);
+                               } catch (InterruptedException e) {
+                                       log.error("Error", e);
+                               }
+                       }
+
+               } catch (Exception e) {
+                       log.error("Error", e);
+               }
+       }
+
+       public int getNumberOfCalls() {
+               return loadTestRtmpClient.getNumberOfCalls();
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8e63647c/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/IDataProviderDao.java
----------------------------------------------------------------------
diff --git 
a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/IDataProviderDao.java
 
b/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/IDataProviderDao.java
index f82f93b..e55e270 100644
--- 
a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/IDataProviderDao.java
+++ 
b/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/IDataProviderDao.java
@@ -1,94 +1,94 @@
-/*
- * 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.db.dao;
-
-import java.util.List;
-
-import org.apache.openmeetings.db.entity.IDataProviderEntity;
-
-/**
- * General interface to perform CRUD operations on entities
- * 
- * @author solomax, swagner
- * 
- * @param <T>
- */
-public interface IDataProviderDao<T extends IDataProviderEntity> {
-
-       /**
-        * Get an instance of an {@link T}
-        * 
-        * @param id - id of instance to retrieve
-        * @return instance with the id gived
-        */
-       T get(Long id);
-
-       T get(long id);
-       
-       /**
-        * Get a list of instances of {@link T}
-        * 
-        * @param start - the start to range to retrieve
-        * @param count - maximum instance count to retrieve
-        * @return list of instances in the range specified
-        */
-       List<T> get(int start, int count);
-
-       /**
-        * Get a list of instances of {@link T}
-        * 
-        * @param search - string search criteria to filter entities
-        * @param start - the start to range to retrieve
-        * @param count - maximum instance count to retrieve
-        * @param order - column and sort order
-        * @return list of instances in the range specified
-        */
-       List<T> get(String search, int start, int count, String order);
-
-       /**
-        * Count the number of instances of {@link T}
-        * 
-        * @return count of instances
-        */
-       long count();
-
-       /**
-        * Count the number of instances of {@link T}
-        * 
-        * @param search - string search criteria to filter entities
-        * @return count of instances satisfying given search criteria
-        */
-       long count(String search);
-
-       /**
-        * Update an instance of {@link T}
-        * 
-        * @param entity - entity to be updated
-        * @param userId - user performed update
-        */
-       T update(T entity, Long userId);
-
-       /**
-        * Delete an instance of {@link T}
-        * 
-        * @param entity - entity to be deleted
-        * @param userId - user performed delete
-        */
-       void delete(T entity, Long userId);
-}
+/*
+ * 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.db.dao;
+
+import java.util.List;
+
+import org.apache.openmeetings.db.entity.IDataProviderEntity;
+
+/**
+ * General interface to perform CRUD operations on entities
+ * 
+ * @author solomax, swagner
+ * 
+ * @param <T>
+ */
+public interface IDataProviderDao<T extends IDataProviderEntity> {
+
+       /**
+        * Get an instance of an {@link T}
+        * 
+        * @param id - id of instance to retrieve
+        * @return instance with the id gived
+        */
+       T get(Long id);
+
+       T get(long id);
+       
+       /**
+        * Get a list of instances of {@link T}
+        * 
+        * @param start - the start to range to retrieve
+        * @param count - maximum instance count to retrieve
+        * @return list of instances in the range specified
+        */
+       List<T> get(int start, int count);
+
+       /**
+        * Get a list of instances of {@link T}
+        * 
+        * @param search - string search criteria to filter entities
+        * @param start - the start to range to retrieve
+        * @param count - maximum instance count to retrieve
+        * @param order - column and sort order
+        * @return list of instances in the range specified
+        */
+       List<T> get(String search, int start, int count, String order);
+
+       /**
+        * Count the number of instances of {@link T}
+        * 
+        * @return count of instances
+        */
+       long count();
+
+       /**
+        * Count the number of instances of {@link T}
+        * 
+        * @param search - string search criteria to filter entities
+        * @return count of instances satisfying given search criteria
+        */
+       long count(String search);
+
+       /**
+        * Update an instance of {@link T}
+        * 
+        * @param entity - entity to be updated
+        * @param userId - user performed update
+        */
+       T update(T entity, Long userId);
+
+       /**
+        * Delete an instance of {@link T}
+        * 
+        * @param entity - entity to be deleted
+        * @param userId - user performed delete
+        */
+       void delete(T entity, Long userId);
+}

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8e63647c/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/basic/MailMessageDao.java
----------------------------------------------------------------------
diff --git 
a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/basic/MailMessageDao.java
 
b/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/basic/MailMessageDao.java
index 2f62dbb..aed66db 100644
--- 
a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/basic/MailMessageDao.java
+++ 
b/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/basic/MailMessageDao.java
@@ -1,135 +1,135 @@
-/*
- * 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.db.dao.basic;
-
-import java.util.Calendar;
-import java.util.List;
-
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
-import javax.persistence.TypedQuery;
-
-import org.apache.openmeetings.db.dao.IDataProviderDao;
-import org.apache.openmeetings.db.entity.basic.MailMessage;
-import org.apache.openmeetings.db.entity.basic.MailMessage.Status;
-import org.apache.wicket.util.string.Strings;
-import org.springframework.transaction.annotation.Transactional;
-
-@Transactional
-public class MailMessageDao  implements IDataProviderDao<MailMessage> {
-       @PersistenceContext
-       private EntityManager em;
-
-       @Override
-       public MailMessage get(long id) {
-               return get(Long.valueOf(id));
-       }
-
-       @Override
-       public MailMessage get(Long id) {
-               return em.createNamedQuery("getMailMessageById", 
MailMessage.class).setParameter("id", id).getSingleResult();
-       }
-
-       @Override
-       public List<MailMessage> get(int start, int count) {
-               return em.createNamedQuery("getMailMessages", MailMessage.class)
-                               
.setFirstResult(start).setMaxResults(count).getResultList();
-       }
-
-       public List<MailMessage> get(int start, int count, Status status) {
-               return em.createNamedQuery("getMailMessagesByStatus", 
MailMessage.class).setParameter("status", status)
-                               
.setFirstResult(start).setMaxResults(count).getResultList();
-       }
-
-       private <T> TypedQuery<T> getQuery(boolean isCount, String search, 
String order, Class<T> clazz) {
-               StringBuilder sb = new StringBuilder("SELECT ");
-               sb.append(isCount ? "COUNT(m)" : "m")
-                       .append(" FROM MailMessage m");
-               if (!Strings.isEmpty(search)) {
-                       sb.append(" WHERE m.recipients LIKE :search OR 
m.subject LIKE :search OR m.body LIKE :search OR m.lastError LIKE :search");
-               }
-               if (!Strings.isEmpty(order)) {
-                       sb.append(" ORDER BY m.").append(order);
-               }
-               TypedQuery<T> q = em.createQuery(sb.toString(), clazz);
-               if (!Strings.isEmpty(search)) {
-                       q.setParameter("search", String.format("%%%s%%", 
search));
-               }
-               return q;
-       }
-
-       @Override
-       public List<MailMessage> get(String search, int start, int count, 
String order) {
-               return getQuery(false, search, order, 
MailMessage.class).setFirstResult(start).setMaxResults(count).getResultList();
-       }
-
-       @Override
-       public long count() {
-               return em.createNamedQuery("countMailMessages", 
Long.class).getSingleResult();
-       }
-
-       @Override
-       public long count(String search) {
-               return getQuery(true, search, null, 
Long.class).getSingleResult();
-       }
-
-       public void resetSendingStatus(Calendar date) {
-               em.createNamedQuery("resetMailStatusByDate")
-                       .setParameter("noneStatus", Status.NONE)
-                       .setParameter("sendingStatus", Status.SENDING)
-                       .setParameter("date", date)
-                       .executeUpdate();
-       }
-
-       public void resetSendingStatus(Long id) {
-               em.createNamedQuery("resetMailStatusById")
-                       .setParameter("noneStatus", Status.NONE)
-                       .setParameter("id", id)
-                       .executeUpdate();
-       }
-
-       @Override
-       public MailMessage update(MailMessage m, Long userId) {
-               if (m.getId() == null) {
-                       m.setInserted(Calendar.getInstance());
-                       em.persist(m);
-               } else {
-                       m.setUpdated(Calendar.getInstance());
-                       m =     em.merge(m);
-               }
-               return m;
-       }
-
-       @Override
-       public void delete(MailMessage m, Long userId) {
-               if (m != null) {
-                       delete(m.getId(), userId);
-               }
-       }
-
-       /**
-        * @param id - entity id
-        * @param userId - unused
-        */
-       public void delete(Long id, Long userId) {
-               if (id != null) {
-                       em.remove(get(id));
-               }
-       }
-}
+/*
+ * 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.db.dao.basic;
+
+import java.util.Calendar;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.TypedQuery;
+
+import org.apache.openmeetings.db.dao.IDataProviderDao;
+import org.apache.openmeetings.db.entity.basic.MailMessage;
+import org.apache.openmeetings.db.entity.basic.MailMessage.Status;
+import org.apache.wicket.util.string.Strings;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+public class MailMessageDao  implements IDataProviderDao<MailMessage> {
+       @PersistenceContext
+       private EntityManager em;
+
+       @Override
+       public MailMessage get(long id) {
+               return get(Long.valueOf(id));
+       }
+
+       @Override
+       public MailMessage get(Long id) {
+               return em.createNamedQuery("getMailMessageById", 
MailMessage.class).setParameter("id", id).getSingleResult();
+       }
+
+       @Override
+       public List<MailMessage> get(int start, int count) {
+               return em.createNamedQuery("getMailMessages", MailMessage.class)
+                               
.setFirstResult(start).setMaxResults(count).getResultList();
+       }
+
+       public List<MailMessage> get(int start, int count, Status status) {
+               return em.createNamedQuery("getMailMessagesByStatus", 
MailMessage.class).setParameter("status", status)
+                               
.setFirstResult(start).setMaxResults(count).getResultList();
+       }
+
+       private <T> TypedQuery<T> getQuery(boolean isCount, String search, 
String order, Class<T> clazz) {
+               StringBuilder sb = new StringBuilder("SELECT ");
+               sb.append(isCount ? "COUNT(m)" : "m")
+                       .append(" FROM MailMessage m");
+               if (!Strings.isEmpty(search)) {
+                       sb.append(" WHERE m.recipients LIKE :search OR 
m.subject LIKE :search OR m.body LIKE :search OR m.lastError LIKE :search");
+               }
+               if (!Strings.isEmpty(order)) {
+                       sb.append(" ORDER BY m.").append(order);
+               }
+               TypedQuery<T> q = em.createQuery(sb.toString(), clazz);
+               if (!Strings.isEmpty(search)) {
+                       q.setParameter("search", String.format("%%%s%%", 
search));
+               }
+               return q;
+       }
+
+       @Override
+       public List<MailMessage> get(String search, int start, int count, 
String order) {
+               return getQuery(false, search, order, 
MailMessage.class).setFirstResult(start).setMaxResults(count).getResultList();
+       }
+
+       @Override
+       public long count() {
+               return em.createNamedQuery("countMailMessages", 
Long.class).getSingleResult();
+       }
+
+       @Override
+       public long count(String search) {
+               return getQuery(true, search, null, 
Long.class).getSingleResult();
+       }
+
+       public void resetSendingStatus(Calendar date) {
+               em.createNamedQuery("resetMailStatusByDate")
+                       .setParameter("noneStatus", Status.NONE)
+                       .setParameter("sendingStatus", Status.SENDING)
+                       .setParameter("date", date)
+                       .executeUpdate();
+       }
+
+       public void resetSendingStatus(Long id) {
+               em.createNamedQuery("resetMailStatusById")
+                       .setParameter("noneStatus", Status.NONE)
+                       .setParameter("id", id)
+                       .executeUpdate();
+       }
+
+       @Override
+       public MailMessage update(MailMessage m, Long userId) {
+               if (m.getId() == null) {
+                       m.setInserted(Calendar.getInstance());
+                       em.persist(m);
+               } else {
+                       m.setUpdated(Calendar.getInstance());
+                       m =     em.merge(m);
+               }
+               return m;
+       }
+
+       @Override
+       public void delete(MailMessage m, Long userId) {
+               if (m != null) {
+                       delete(m.getId(), userId);
+               }
+       }
+
+       /**
+        * @param id - entity id
+        * @param userId - unused
+        */
+       public void delete(Long id, Long userId) {
+               if (id != null) {
+                       em.remove(get(id));
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/8e63647c/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/label/LabelDao.java
----------------------------------------------------------------------
diff --git 
a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/label/LabelDao.java
 
b/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/label/LabelDao.java
index 4a51331..efcdaaa 100644
--- 
a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/label/LabelDao.java
+++ 
b/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/label/LabelDao.java
@@ -1,321 +1,321 @@
-/*
- * 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.db.dao.label;
-
-import static 
org.apache.openmeetings.db.util.ApplicationHelper.ensureApplication;
-import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.InvalidPropertiesFormatException;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.Predicate;
-import org.apache.openmeetings.db.dao.IDataProviderDao;
-import org.apache.openmeetings.db.entity.label.StringLabel;
-import org.apache.openmeetings.util.OmFileHelper;
-import org.apache.openmeetings.util.XmlExport;
-import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
-import org.apache.wicket.util.string.Strings;
-import org.dom4j.Document;
-import org.dom4j.Element;
-import org.dom4j.io.SAXReader;
-import org.red5.logging.Red5LoggerFactory;
-import org.slf4j.Logger;
-
-/**
- *
- * CRUD operations for {@link StringLabel}
- *
- * @author solomax, swagner
- *
- */
-public class LabelDao implements IDataProviderDao<StringLabel>{
-       private static final Logger log = 
Red5LoggerFactory.getLogger(LabelDao.class, webAppRootKey);
-       private static final String ENTRY_ELEMENT = "entry";
-       private static final String KEY_ATTR = "key";
-       public static final String APP_RESOURCES_EN = 
"Application.properties.xml";
-       public static final String APP_RESOURCES = 
"Application_%s.properties.xml";
-       public static final LinkedHashMap<Long, Locale> languages = new 
LinkedHashMap<>(); //TODO hide it and return unmodifiable map
-       public static final ConcurrentHashMap<Locale, List<StringLabel>> 
labelCache = new ConcurrentHashMap<>();
-       public static final Set<String> keys = new HashSet<>();
-       private static Class<?> APP = null;
-
-       public List<Map<String, Object>> getStrings(Long language_id, int 
start, int count) {
-               List<Map<String, Object>> result = new ArrayList<>();
-               for (int i = 0; i < count; ++i) {
-                       Map<String, Object> map = new HashMap<>();
-                       map.put("id", start + i);
-                       map.put("value", getString(start + i, language_id));
-                       result.add(map);
-               }
-               return result;
-       }
-
-       private static void storeLanguages() throws Exception {
-               Document d = XmlExport.createDocument();
-               Element r = XmlExport.createRoot(d, "language");
-               for (Map.Entry<Long, Locale> e : languages.entrySet()) {
-                       r.addElement("lang").addAttribute("id", "" + 
e.getKey()).addAttribute("code", e.getValue().toLanguageTag());
-               }
-               XmlExport.toXml(getLangFile(), d);
-       }
-
-       public static void add(Locale l) throws Exception {
-               long id = 0L;
-               for (Map.Entry<Long, Locale> e : languages.entrySet()) {
-                       id = e.getKey();
-               }
-               languages.put(id + 1, l);
-               storeLanguages();
-               labelCache.put(l, new ArrayList<StringLabel>());
-       }
-
-       public String getString(long fieldValuesId, long langId) {
-               return ensureApplication(langId).getOmString(fieldValuesId, 
langId);
-       }
-
-       public String getString(String key, long langId) {
-               return ensureApplication(langId).getOmString(key, langId);
-       }
-
-       private static File getLangFile() {
-               return new File(OmFileHelper.getLanguagesDir(), 
OmFileHelper.nameOfLanguageFile);
-       }
-
-       public static synchronized Class<?> getAppClass() throws 
ClassNotFoundException {
-               if (APP == null) {
-                       //FIXME HACK to resolve package dependencies
-                       APP = 
Class.forName("org.apache.openmeetings.web.app.Application");
-               }
-               return APP;
-       }
-
-       public static void initLanguageMap() {
-               SAXReader reader = new SAXReader();
-               try {
-                       getAppClass();
-                       Document document = reader.read(getLangFile());
-                       Element root = document.getRootElement();
-                       languages.clear();
-                       for (@SuppressWarnings("unchecked")Iterator<Element> it 
= root.elementIterator("lang"); it.hasNext();) {
-                               Element item = it.next();
-                               Long id = 
Long.valueOf(item.attributeValue("id"));
-                               String code = item.attributeValue("code");
-                               if (id == 3L) {
-                                       continue;
-                               }
-                               languages.put(id, Locale.forLanguageTag(code));
-                       }
-               } catch (Exception e) {
-                       log.error("Error while building language map");
-               }
-       }
-
-       public static String getLabelFileName(Locale l) {
-               String name = APP_RESOURCES_EN;
-               if (!Locale.ENGLISH.equals(l)) {
-                       name = String.format(APP_RESOURCES, 
l.toLanguageTag().replace('-', '_'));
-               }
-               return name;
-       }
-
-       private static void storeLabels(Locale l) throws Exception {
-               Document d = XmlExport.createDocument();
-               Element r = XmlExport.createRoot(d);
-               List<StringLabel> labels = labelCache.get(l);
-               for (StringLabel sl : labels) {
-                       r.addElement(ENTRY_ELEMENT).addAttribute(KEY_ATTR, 
sl.getKey()).addCDATA(sl.getValue());
-               }
-               URL u = APP.getResource(getLabelFileName(l));
-               XmlExport.toXml(new File(u.toURI()), d);
-       }
-
-       public static void upload(Locale l, InputStream is) throws Exception {
-               List<StringLabel> labels = getLabels(is);
-               URL u = APP.getResource(getLabelFileName(Locale.ENGLISH)); 
//get the URL of existing resource
-               File el = new File(u.toURI());
-               File f = new File(el.getParentFile(), getLabelFileName(l));
-               if (!f.exists()) {
-                       f.createNewFile();
-               }
-               labelCache.put(l, labels);
-               storeLabels(l);
-       }
-
-       private static List<StringLabel> getLabels(Locale l) {
-               List<StringLabel> labels = new ArrayList<>();
-               try (InputStream is = 
APP.getResourceAsStream(getLabelFileName(l))) {
-                       labels = getLabels(is);
-               } catch (Exception e) {
-                       log.error("Error reading resources document", e);
-               }
-               return labels;
-       }
-
-       private static List<StringLabel> getLabels(InputStream is) throws 
InvalidPropertiesFormatException, IOException {
-               final List<StringLabel> labels = new ArrayList<>();
-               Properties props = new Properties();
-               props.loadFromXML(is);
-               props.forEach((k, v) -> labels.add(new StringLabel((String)k, 
(String)v)));
-               return labels;
-       }
-
-       private static List<StringLabel> getLabels(Locale l, final String 
search) {
-               if (!labelCache.containsKey(l)) {
-                       List<StringLabel> ll = getLabels(l);
-                       if (ll != null) {
-                               labelCache.putIfAbsent(l, ll);
-                       }
-               }
-               List<StringLabel> result = new 
ArrayList<>(labelCache.containsKey(l) ? labelCache.get(l) : new 
ArrayList<StringLabel>());
-               if (!Strings.isEmpty(search)) {
-                       CollectionUtils.filter(result, new 
Predicate<StringLabel>() {
-                               @Override
-                               public boolean evaluate(StringLabel o) {
-                                       return o != null && 
(o.getKey().contains(search) || o.getValue().contains(search));
-                               }
-                       });
-               }
-               return result;
-       }
-
-       @Override
-       public StringLabel get(long id) {
-               throw new RuntimeException("Should not be used");
-       }
-
-       @Override
-       public StringLabel get(Long id) {
-               throw new RuntimeException("Should not be used");
-       }
-
-       @Override
-       public List<StringLabel> get(int start, int count) {
-               throw new RuntimeException("Should not be used");
-       }
-
-       @Override
-       public List<StringLabel> get(String search, int start, int count, 
String order) {
-               throw new RuntimeException("Should not be used");
-       }
-
-       public List<StringLabel> get(Locale l, final String search, int start, 
int count, final SortParam<String> sort) {
-               List<StringLabel> result = getLabels(l, search);
-               if (sort != null) {
-                       Collections.sort(result, new Comparator<StringLabel>() {
-                               @Override
-                               public int compare(StringLabel o1, StringLabel 
o2) {
-                                       int val = 0;
-                                       if 
(KEY_ATTR.equals(sort.getProperty())) {
-                                               try {
-                                                       int i1 = 
Integer.parseInt(o1.getKey()), i2 = Integer.parseInt(o2.getKey());
-                                                       val = i1 - i2;
-                                               } catch (Exception e) {
-                                                       val = 
o1.getKey().compareTo(o2.getKey());
-                                               }
-                                       } else {
-                                               val = 
o1.getValue().compareTo(o2.getValue());
-                                       }
-                                       return (sort.isAscending() ? 1 : -1) * 
val;
-                               }
-                       });
-               }
-               return result.subList(start, start + count > result.size() ? 
result.size() : start + count);
-       }
-
-       @Override
-       public long count() {
-               throw new RuntimeException("Should not be used");
-       }
-
-       @Override
-       public long count(String search) {
-               throw new RuntimeException("Should not be used");
-       }
-
-       public long count(Locale l, final String search) {
-               return getLabels(l, search).size();
-       }
-
-       @Override
-       public StringLabel update(StringLabel entity, Long userId) {
-               throw new RuntimeException("Should not be used");
-       }
-
-       public StringLabel update(Locale l, StringLabel entity) throws 
Exception {
-               List<StringLabel> labels = labelCache.get(l);
-               if (!labels.contains(entity)) {
-                       labels.add(entity);
-                       keys.add(entity.getKey());
-               }
-               storeLabels(l);
-               return entity;
-       }
-
-       @Override
-       public void delete(StringLabel entity, Long userId) {
-               throw new RuntimeException("Should not be used");
-       }
-
-       public void delete(Locale l, StringLabel entity) throws Exception {
-               List<StringLabel> labels = labelCache.get(l);
-               if (labels.contains(entity)) {
-                       labels.remove(entity);
-                       keys.remove(entity.getKey());
-                       storeLabels(l);
-               }
-       }
-
-       public static void delete(Locale l) {
-               for (Map.Entry<Long, Locale> e : languages.entrySet()) {
-                       if (e.getValue().equals(l)) {
-                               languages.remove(e.getKey());
-                               break;
-                       }
-               }
-               labelCache.remove(l);
-               try {
-                       URL u = APP.getResource(getLabelFileName(l));
-                       if (u != null) {
-                               File f = new File(u.toURI());
-                               if (f.exists()) {
-                                       f.delete();
-                               }
-                       }
-               } catch (Exception e) {
-                       log.error("Unexpected error while deleting language", 
e);
-               }
-       }
-}
+/*
+ * 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.db.dao.label;
+
+import static 
org.apache.openmeetings.db.util.ApplicationHelper.ensureApplication;
+import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.InvalidPropertiesFormatException;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.openmeetings.db.dao.IDataProviderDao;
+import org.apache.openmeetings.db.entity.label.StringLabel;
+import org.apache.openmeetings.util.OmFileHelper;
+import org.apache.openmeetings.util.XmlExport;
+import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
+import org.apache.wicket.util.string.Strings;
+import org.dom4j.Document;
+import org.dom4j.Element;
+import org.dom4j.io.SAXReader;
+import org.red5.logging.Red5LoggerFactory;
+import org.slf4j.Logger;
+
+/**
+ *
+ * CRUD operations for {@link StringLabel}
+ *
+ * @author solomax, swagner
+ *
+ */
+public class LabelDao implements IDataProviderDao<StringLabel>{
+       private static final Logger log = 
Red5LoggerFactory.getLogger(LabelDao.class, webAppRootKey);
+       private static final String ENTRY_ELEMENT = "entry";
+       private static final String KEY_ATTR = "key";
+       public static final String APP_RESOURCES_EN = 
"Application.properties.xml";
+       public static final String APP_RESOURCES = 
"Application_%s.properties.xml";
+       public static final LinkedHashMap<Long, Locale> languages = new 
LinkedHashMap<>(); //TODO hide it and return unmodifiable map
+       public static final ConcurrentHashMap<Locale, List<StringLabel>> 
labelCache = new ConcurrentHashMap<>();
+       public static final Set<String> keys = new HashSet<>();
+       private static Class<?> APP = null;
+
+       public List<Map<String, Object>> getStrings(Long language_id, int 
start, int count) {
+               List<Map<String, Object>> result = new ArrayList<>();
+               for (int i = 0; i < count; ++i) {
+                       Map<String, Object> map = new HashMap<>();
+                       map.put("id", start + i);
+                       map.put("value", getString(start + i, language_id));
+                       result.add(map);
+               }
+               return result;
+       }
+
+       private static void storeLanguages() throws Exception {
+               Document d = XmlExport.createDocument();
+               Element r = XmlExport.createRoot(d, "language");
+               for (Map.Entry<Long, Locale> e : languages.entrySet()) {
+                       r.addElement("lang").addAttribute("id", "" + 
e.getKey()).addAttribute("code", e.getValue().toLanguageTag());
+               }
+               XmlExport.toXml(getLangFile(), d);
+       }
+
+       public static void add(Locale l) throws Exception {
+               long id = 0L;
+               for (Map.Entry<Long, Locale> e : languages.entrySet()) {
+                       id = e.getKey();
+               }
+               languages.put(id + 1, l);
+               storeLanguages();
+               labelCache.put(l, new ArrayList<StringLabel>());
+       }
+
+       public String getString(long fieldValuesId, long langId) {
+               return ensureApplication(langId).getOmString(fieldValuesId, 
langId);
+       }
+
+       public String getString(String key, long langId) {
+               return ensureApplication(langId).getOmString(key, langId);
+       }
+
+       private static File getLangFile() {
+               return new File(OmFileHelper.getLanguagesDir(), 
OmFileHelper.nameOfLanguageFile);
+       }
+
+       public static synchronized Class<?> getAppClass() throws 
ClassNotFoundException {
+               if (APP == null) {
+                       //FIXME HACK to resolve package dependencies
+                       APP = 
Class.forName("org.apache.openmeetings.web.app.Application");
+               }
+               return APP;
+       }
+
+       public static void initLanguageMap() {
+               SAXReader reader = new SAXReader();
+               try {
+                       getAppClass();
+                       Document document = reader.read(getLangFile());
+                       Element root = document.getRootElement();
+                       languages.clear();
+                       for (@SuppressWarnings("unchecked")Iterator<Element> it 
= root.elementIterator("lang"); it.hasNext();) {
+                               Element item = it.next();
+                               Long id = 
Long.valueOf(item.attributeValue("id"));
+                               String code = item.attributeValue("code");
+                               if (id == 3L) {
+                                       continue;
+                               }
+                               languages.put(id, Locale.forLanguageTag(code));
+                       }
+               } catch (Exception e) {
+                       log.error("Error while building language map");
+               }
+       }
+
+       public static String getLabelFileName(Locale l) {
+               String name = APP_RESOURCES_EN;
+               if (!Locale.ENGLISH.equals(l)) {
+                       name = String.format(APP_RESOURCES, 
l.toLanguageTag().replace('-', '_'));
+               }
+               return name;
+       }
+
+       private static void storeLabels(Locale l) throws Exception {
+               Document d = XmlExport.createDocument();
+               Element r = XmlExport.createRoot(d);
+               List<StringLabel> labels = labelCache.get(l);
+               for (StringLabel sl : labels) {
+                       r.addElement(ENTRY_ELEMENT).addAttribute(KEY_ATTR, 
sl.getKey()).addCDATA(sl.getValue());
+               }
+               URL u = APP.getResource(getLabelFileName(l));
+               XmlExport.toXml(new File(u.toURI()), d);
+       }
+
+       public static void upload(Locale l, InputStream is) throws Exception {
+               List<StringLabel> labels = getLabels(is);
+               URL u = APP.getResource(getLabelFileName(Locale.ENGLISH)); 
//get the URL of existing resource
+               File el = new File(u.toURI());
+               File f = new File(el.getParentFile(), getLabelFileName(l));
+               if (!f.exists()) {
+                       f.createNewFile();
+               }
+               labelCache.put(l, labels);
+               storeLabels(l);
+       }
+
+       private static List<StringLabel> getLabels(Locale l) {
+               List<StringLabel> labels = new ArrayList<>();
+               try (InputStream is = 
APP.getResourceAsStream(getLabelFileName(l))) {
+                       labels = getLabels(is);
+               } catch (Exception e) {
+                       log.error("Error reading resources document", e);
+               }
+               return labels;
+       }
+
+       private static List<StringLabel> getLabels(InputStream is) throws 
InvalidPropertiesFormatException, IOException {
+               final List<StringLabel> labels = new ArrayList<>();
+               Properties props = new Properties();
+               props.loadFromXML(is);
+               props.forEach((k, v) -> labels.add(new StringLabel((String)k, 
(String)v)));
+               return labels;
+       }
+
+       private static List<StringLabel> getLabels(Locale l, final String 
search) {
+               if (!labelCache.containsKey(l)) {
+                       List<StringLabel> ll = getLabels(l);
+                       if (ll != null) {
+                               labelCache.putIfAbsent(l, ll);
+                       }
+               }
+               List<StringLabel> result = new 
ArrayList<>(labelCache.containsKey(l) ? labelCache.get(l) : new 
ArrayList<StringLabel>());
+               if (!Strings.isEmpty(search)) {
+                       CollectionUtils.filter(result, new 
Predicate<StringLabel>() {
+                               @Override
+                               public boolean evaluate(StringLabel o) {
+                                       return o != null && 
(o.getKey().contains(search) || o.getValue().contains(search));
+                               }
+                       });
+               }
+               return result;
+       }
+
+       @Override
+       public StringLabel get(long id) {
+               throw new RuntimeException("Should not be used");
+       }
+
+       @Override
+       public StringLabel get(Long id) {
+               throw new RuntimeException("Should not be used");
+       }
+
+       @Override
+       public List<StringLabel> get(int start, int count) {
+               throw new RuntimeException("Should not be used");
+       }
+
+       @Override
+       public List<StringLabel> get(String search, int start, int count, 
String order) {
+               throw new RuntimeException("Should not be used");
+       }
+
+       public List<StringLabel> get(Locale l, final String search, int start, 
int count, final SortParam<String> sort) {
+               List<StringLabel> result = getLabels(l, search);
+               if (sort != null) {
+                       Collections.sort(result, new Comparator<StringLabel>() {
+                               @Override
+                               public int compare(StringLabel o1, StringLabel 
o2) {
+                                       int val = 0;
+                                       if 
(KEY_ATTR.equals(sort.getProperty())) {
+                                               try {
+                                                       int i1 = 
Integer.parseInt(o1.getKey()), i2 = Integer.parseInt(o2.getKey());
+                                                       val = i1 - i2;
+                                               } catch (Exception e) {
+                                                       val = 
o1.getKey().compareTo(o2.getKey());
+                                               }
+                                       } else {
+                                               val = 
o1.getValue().compareTo(o2.getValue());
+                                       }
+                                       return (sort.isAscending() ? 1 : -1) * 
val;
+                               }
+                       });
+               }
+               return result.subList(start, start + count > result.size() ? 
result.size() : start + count);
+       }
+
+       @Override
+       public long count() {
+               throw new RuntimeException("Should not be used");
+       }
+
+       @Override
+       public long count(String search) {
+               throw new RuntimeException("Should not be used");
+       }
+
+       public long count(Locale l, final String search) {
+               return getLabels(l, search).size();
+       }
+
+       @Override
+       public StringLabel update(StringLabel entity, Long userId) {
+               throw new RuntimeException("Should not be used");
+       }
+
+       public StringLabel update(Locale l, StringLabel entity) throws 
Exception {
+               List<StringLabel> labels = labelCache.get(l);
+               if (!labels.contains(entity)) {
+                       labels.add(entity);
+                       keys.add(entity.getKey());
+               }
+               storeLabels(l);
+               return entity;
+       }
+
+       @Override
+       public void delete(StringLabel entity, Long userId) {
+               throw new RuntimeException("Should not be used");
+       }
+
+       public void delete(Locale l, StringLabel entity) throws Exception {
+               List<StringLabel> labels = labelCache.get(l);
+               if (labels.contains(entity)) {
+                       labels.remove(entity);
+                       keys.remove(entity.getKey());
+                       storeLabels(l);
+               }
+       }
+
+       public static void delete(Locale l) {
+               for (Map.Entry<Long, Locale> e : languages.entrySet()) {
+                       if (e.getValue().equals(l)) {
+                               languages.remove(e.getKey());
+                               break;
+                       }
+               }
+               labelCache.remove(l);
+               try {
+                       URL u = APP.getResource(getLabelFileName(l));
+                       if (u != null) {
+                               File f = new File(u.toURI());
+                               if (f.exists()) {
+                                       f.delete();
+                               }
+                       }
+               } catch (Exception e) {
+                       log.error("Unexpected error while deleting language", 
e);
+               }
+       }
+}

Reply via email to