You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openmeetings.apache.org by so...@apache.org on 2017/05/18 05:39:22 UTC

[22/23] openmeetings git commit: Normalize all the line endings

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);
+		}
+	}
+}