package eu.musesproject.server.connectionmanager;
/*
* #%L
* MUSES Server
* %%
* Copyright (C) 2013 - 2014 Sweden Connectivity
* %%
* 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.
* #L%
*/
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
/**
* Class Connection Manager
*
* @author Yasir Ali
* @version Jan 27, 2014
*/
public class ConnectionManager implements IConnectionManager{
private static Logger logger = Logger.getLogger(ConnectionManager.class.getName());
private static IConnectionCallbacks callBacks; // this one is registered in ComMainServlet.init().
//private DataHandler dataHandler; // multiple thread will have access to connectionmanager singleton. therefore we can not have this instance variable.
// private SessionHandler sessionCounter; // the sessionHandler class have been disabled is not going to be used anymore.
private static ConnectionManager connectionManagerSingleton = null;
//private static Queue<DataHandler> dataHandlerQueue = new LinkedList<DataHandler>(); // this queue will be accessed by many threads. thread-safety is mandatory.
// the queue should store info based on username and device id because session id can change and that will cause the queue to grow indefinitely.
private static Queue<DataHandler> dataHandlerQueue = new ConcurrentLinkedQueue<DataHandler>(); // this concrete implementation of queue interface is thread-safe.
private static final String MUSES_TAG = "MUSES_TAG";
private static final String MUSES_TAG_LEVEL_2 = "MUSES_TAG_LEVEL_2";
// /**
// * Constructor initialises callback
// * @param calBacks
// */
// public ConnectionManager(IConnectionCallbacks iCallbacks){ // FIXME this constrctor is used by Unit test only
// callBacks = iCallbacks;
// }
private ConnectionManager() {
//sessionCounter = new SessionHandler();
}
/**
* Creare Communication manager singleton if not created
* @return singleton object
*/
public static ConnectionManager getInstance(){
// this is the old non thread-safe code. assume the singleton has not yet been assigned and then two threads at the same time check to see if the
// singleton is null. both will create their own instance which will defeat the purpose of a singleton. the correct thread-safe version
// is available below.
// if (connectionManagerSingleton == null) {
// connectionManagerSingleton = new ConnectionManager();
// }
// return connectionManagerSingleton;
if (connectionManagerSingleton == null) {
synchronized(ConnectionManager.class){
if (connectionManagerSingleton == null) {
connectionManagerSingleton = new ConnectionManager();
}
}
}
return connectionManagerSingleton;
}
/**
* Sends data back to client with associate session ID
* @param String sessionId
* @param String dta
* @return void
*/
@Override
public void sendData(String sessionId, String dta) { // FIXME if several packets are sent with same session ID there is no way to find out which one was sent
if (sessionId != null && dta != null && !dta.equals("")) {
logger.log(Level.INFO, MUSES_TAG_LEVEL_2 +" Data added in queue with ID:" + sessionId);
DataHandler dataHandler = new DataHandler(sessionId, dta);
addDataHandler(dataHandler);
}
}
// /**
// * Get all sessionIds
// * @return Set<String>
// */
// @Override
// public Set<String> getSessionIds() {
// return sessionCounter.getSessionIds();
// }
/**
* Registers for callbacks
* @param ICallBacks iCallBacks
* @return void
*/
@Override
public void registerReceiveCb(IConnectionCallbacks iCallBacks) {
// FIXME how to handle the return status
if (iCallBacks != null){
callBacks = iCallBacks;
logger.log(Level.INFO, "callback registered");
} else {
logger.log(Level.INFO, "Passed callback is null");
}
}
/**
* Called by connection manager to send data received from the client
* @param sessionID
* @param dataAttachedInCurrentReuqest
* @return data received from the client
*/
public static String toReceive(String sessionID, String dataAttachedInCurrentReuqest){
if (callBacks != null){
return callBacks.receiveCb(sessionID, dataAttachedInCurrentReuqest);
} else {
logger.log(Level.INFO, "Callback object is null");// logg
}
return null;
}
/**
* This method is used by connection manager to add data handler object
* @param dataHandler
* @return void
*/
public static synchronized void addDataHandler(DataHandler dataHandler){
dataHandlerQueue.add(dataHandler);
}
/**
* This method is used by connection manager to remove data handler object
* @param dataHandler
* @return void
*/
public synchronized void removeDataHandler(DataHandler dataHandler) {
dataHandlerQueue.remove(dataHandler);
}
/**
* This method is used by connection manager to get data handler object with session id
* @param session
* @return void
*/
public synchronized DataHandler getDataHandlerObject(String sessionId){
if (!dataHandlerQueue.isEmpty()) {
for (DataHandler d : dataHandlerQueue){
if(d.getSessionId().equalsIgnoreCase(sessionId)){
return d;
}
}
}
return null;
}
/**
* Get data handler objects list
* @return
*/
public synchronized Queue<DataHandler> getDataHandlerQueue() {
return dataHandlerQueue;
}
/**
* This method is called to session status
* @param sessionId
* @param status
* @return void
*/
public static void toSessionCb(String sessionId, int status){
if (callBacks!=null){
callBacks.sessionCb(sessionId, status);
} else {
logger.log(Level.INFO, "Callback object is null");
}
}
}