From ecaed684fc00f4c4688250ef8e460a2bcf02438d Mon Sep 17 00:00:00 2001 From: SeekDaSky Date: Fri, 8 Dec 2017 02:38:07 +0100 Subject: [PATCH] refactoring des chanels : classe parente abstraite --- src/Channels/AbstractChannel.kt | 271 ++++++++++++++++++++++++++++++++ src/Channels/Emergency.kt | 261 +----------------------------- src/Channels/Event.kt | 261 +----------------------------- 3 files changed, 277 insertions(+), 516 deletions(-) create mode 100644 src/Channels/AbstractChannel.kt diff --git a/src/Channels/AbstractChannel.kt b/src/Channels/AbstractChannel.kt new file mode 100644 index 0000000..ab0bc2e --- /dev/null +++ b/src/Channels/AbstractChannel.kt @@ -0,0 +1,271 @@ +package Channels + +import Collections.Message +import Collections.Stack +import org.json.JSONArray +import org.json.JSONObject +import seekdasky.kWebSocket.Client +import seekdasky.kWebSocket.Event +import seekdasky.kWebSocket.Listeners.AsynchronousListener +import seekdasky.kWebSocket.Message.buildTextMessage +import seekdasky.kWebSocket.Server + +abstract class AbstractChannel : AsynchronousListener { + + var clients : MutableList; + val messages : MutableMap>>; + val serv : Server; + abstract val chanName : String; + + constructor(serv : Server){ + this.clients = mutableListOf(); + this.messages = mutableMapOf(); + this.serv = serv; + } + + override fun filter(c: Client): Boolean { + val regex = "\\/$chanName\\/(.*)".toRegex() + val result = regex.findAll(c.URL); + if(result.count() == 1){ + return true; + } + return false; + } + + override fun processClosed(e: Event) { + this.clients.remove(e.client); + ConnectChannel.notifyDisconnect(e.client); + System.out.println("A client disconnected ("+this.clients.count()+" clients connected)"); + } + + override fun processConnection(c: Client) { + this.clients.add(c); + val regex = "\\/$chanName\\/(.*)".toRegex(); + val result = regex.findAll(c.URL).elementAt(0).groups[1]?.value ?: ""; + + //create stack if not present + if(this.messages[result] == null){ + this.messages[result] = Stack( 50); + } + + //bind client to channel + if(c.data["emergencyChannel"] == null){ + c.data["emergencyChannel"] = result; + } + c.data["IsLogged"] = false; + } + + fun manuallyDispatchMessage(channel : String, msg : Message, operation : String){ + + val channelStack = this.messages[channel]; + + if(channelStack != null){ + + synchronized(channelStack, { + channelStack.push(Pair(msg.user,msg)); + }) + + this.dispatchMessage(channel,msg,operation); + }else if (channel == ""){ + //broadcast + for(c in this.messages.values){ + synchronized(c,{ + c.push(Pair(msg.user,msg)); + }) + } + + this.dispatchMessage(channel,msg,operation); + + } + } + + override fun processEvent(e: Event) { + try{ + val json = JSONObject(e.message.getString()) + + //dead code, should remove it later + if(json.has("close")){ + return + } + + //si l'utilisateur n'est pas log, on le check + if(e.client.data["IsLogged"] != true){ + //json format : {username:xxx} + if(json.has("name") && json.getString("name") != null){ + e.client.data["Username"] = json.getString("name"); + + //if the client correctly identified with the Interop server + if(ConnectChannel.isConnected(e.client)){ + //log + System.out.println("Emergency connection ("+this.clients.count()+" clients connected)"); + + //return OK to the client + e.client.data["IsLogged"] = true; + val jsonLogin = JSONObject(); + jsonLogin.put("error",false); + e.client.send(buildTextMessage(jsonLogin.toString())); + + //give the client the list of the most recent messages + val array = JSONObject(); + + val chanMessages = this.messages[e.client.data["emergencyChannel"]]; + if(chanMessages != null){ + synchronized(chanMessages,{ + chanMessages.toList().forEach { + array.put(it.second.id,it.second.toJSON()) + } + }) + } + + //build JSON + val jsonMessage = JSONObject(); + jsonMessage.put("error",false); + jsonMessage.put("add",array); + + e.client.send(buildTextMessage(jsonMessage.toString())); + }else{ + val jsonError = JSONObject(); + jsonError.put("error","Invalid credentials"); + + e.client.send(buildTextMessage(jsonError.toString())); + } + + }else{ + //tried to access chat without logging in + val jsonError = JSONObject(); + jsonError.put("error","You must send your credential before sending anything else"); + + e.client.send(buildTextMessage(jsonError.toString())); + + } + + return; + }else if(json.has("message")){ + val chanMessages = this.messages[e.client.data["emergencyChannel"]]; + val message = Message(); + if(chanMessages != null){ + message.user = e.client.data["Username"].toString(); + message.message = json.getString("message"); + message.id = "-1"; + + var lat : Float; + var lng : Float; + + //javascript may send float as integer so we double check that + try { + lat = (json.getJSONArray("location")[0] as Double).toFloat(); + }catch(e : Exception){ + lat = (json.getJSONArray("location")[0] as Integer).toFloat(); + } + + try { + lng = (json.getJSONArray("location")[1] as Double).toFloat(); + }catch(e : Exception){ + lng = (json.getJSONArray("location")[1] as Integer).toFloat(); + } + + message.location = mutableListOf(lat,lng); + + if(json.has("type")){ + message.type = json.getInt("type"); + } + + synchronized(chanMessages,{ + chanMessages.push(Pair(e.client.data["Username"].toString(),message)) + }); + } + + var chanName = ""; + if(e.client.data["emergencyChannel"] != null){ + chanName = e.client.data["emergencyChannel"].toString(); + } + + for(c in this.clients){ + this.dispatchMessage(chanName,message,"add"); + } + }else{ + System.out.println("unknown JSON: "+json.toString()); + } + }catch (e : Exception){ + //System.out.println("Something went wrong (probably JSON parsing error"); + e.printStackTrace(); + } + } + + fun dispatchMessage(channel: String, message: Message, operation : String){ + + val authorizedOperations = listOf("add","upd","del"); + + if(!authorizedOperations.contains(operation)){ + throw Exception("Unauthorized operation"); + } + + val array = JSONObject(); + array.put(message.id,message.toJSON()) + + val jsonMessage = JSONObject(); + jsonMessage.put("error",false); + + //all operations must be present but can be empty + for (op in authorizedOperations){ + if(op == operation){ + jsonMessage.put(op,array); + }else{ + jsonMessage.put(op, JSONArray()); + } + } + + for(c in this.clients){ + //dispatch message to logged client in the right channel or in any channel if channel is an empty string (broadcast) + if(c.data["IsLogged"] == true && ((channel != "" && c.data["emergencyChannel"] == channel) || channel == "")){ + c.send(buildTextMessage(jsonMessage.toString())); + } + } + } + + fun deleteMessage(id : String){ + this.messages.keys.forEach { + val key = it; + val array = this.messages[it]; + array?.toList()?.forEach{ + if(it.second.id == id){ + array.remove(it); + val msg = Message() + msg.id = id; + this.dispatchMessage(key,msg,"del"); + } + } + } + } + + fun updateMessage(msg : Message){ + this.messages.keys.forEach { + val key = it; + val array = this.messages[it]; + var index = 0; + array?.toList()?.forEach{ + if(it.second.id == msg.id){ + msg.user = it.second.user; + msg.location = it.second.location; + msg.timestamp = it.second.timestamp; + array.set(index,Pair(it.first,msg)); + this.dispatchMessage(key,msg,"upd"); + } + index++; + } + } + } + + fun getMessages(chan : String) : MutableList>{ + val channel = this.messages[chan]?.toList(); + val returned = mutableListOf>() + if(channel != null){ + for (m in channel){ + returned.add(Pair(m.second.id,m.second)); + } + } + + return returned; + } + +} \ No newline at end of file diff --git a/src/Channels/Emergency.kt b/src/Channels/Emergency.kt index b57704a..146fb39 100644 --- a/src/Channels/Emergency.kt +++ b/src/Channels/Emergency.kt @@ -1,265 +1,10 @@ package Channels -import Collections.Message -import Collections.Stack -import org.json.JSONArray -import org.json.JSONObject -import seekdasky.kWebSocket.Client -import seekdasky.kWebSocket.Event -import seekdasky.kWebSocket.Listeners.AsynchronousListener -import seekdasky.kWebSocket.Message.buildTextMessage import seekdasky.kWebSocket.Server -class Emergency : AsynchronousListener { +class Emergency : AbstractChannel { - var clients : MutableList; - val messages : MutableMap>>; - val serv : Server; + override val chanName = "emergency"; - constructor(serv : Server){ - this.clients = mutableListOf(); - this.messages = mutableMapOf(); - this.serv = serv; - } - - override fun filter(c: Client): Boolean { - val regex = "\\/emergency\\/(.*)".toRegex() - val result = regex.findAll(c.URL); - if(result.count() == 1){ - return true; - } - return false; - } - - override fun processClosed(e: Event) { - this.clients.remove(e.client); - ConnectChannel.notifyDisconnect(e.client); - System.out.println("A client disconnected ("+this.clients.count()+" clients connected)"); - } - - override fun processConnection(c: Client) { - this.clients.add(c); - val regex = "\\/emergency\\/(.*)".toRegex(); - val result = regex.findAll(c.URL).elementAt(0).groups[1]?.value ?: ""; - - //create stack if not present - if(this.messages[result] == null){ - this.messages[result] = Stack( 50); - } - - //bind client to channel - if(c.data["emergencyChannel"] == null){ - c.data["emergencyChannel"] = result; - } - c.data["IsLogged"] = false; - } - - fun manuallyDispatchMessage(channel : String, msg : Message, operation : String){ - - val channelStack = this.messages[channel]; - - if(channelStack != null){ - - synchronized(channelStack, { - channelStack.push(Pair(msg.user,msg)); - }) - - this.dispatchMessage(channel,msg,operation); - }else if (channel == ""){ - //broadcast - for(c in this.messages.values){ - synchronized(c,{ - c.push(Pair(msg.user,msg)); - }) - } - - this.dispatchMessage(channel,msg,operation); - - } - } - - override fun processEvent(e: Event) { - try{ - val json = JSONObject(e.message.getString()) - - //dead code, should remove it later - if(json.has("close")){ - return - } - - //si l'utilisateur n'est pas log, on le check - if(e.client.data["IsLogged"] != true){ - //json format : {username:xxx} - if(json.has("name") && json.getString("name") != null){ - e.client.data["Username"] = json.getString("name"); - - //if the client correctly identified with the Interop server - if(ConnectChannel.isConnected(e.client)){ - //log - System.out.println("Emergency connection ("+this.clients.count()+" clients connected)"); - - //return OK to the client - e.client.data["IsLogged"] = true; - val jsonLogin = JSONObject(); - jsonLogin.put("error",false); - e.client.send(buildTextMessage(jsonLogin.toString())); - - //give the client the list of the most recent messages - val array = JSONObject(); - - val chanMessages = this.messages[e.client.data["emergencyChannel"]]; - if(chanMessages != null){ - synchronized(chanMessages,{ - chanMessages.toList().forEach { - array.put(it.second.id,it.second.toJSON()) - } - }) - } - - //build JSON - val jsonMessage = JSONObject(); - jsonMessage.put("error",false); - jsonMessage.put("add",array); - - e.client.send(buildTextMessage(jsonMessage.toString())); - }else{ - val jsonError = JSONObject(); - jsonError.put("error","Invalid credentials"); - - e.client.send(buildTextMessage(jsonError.toString())); - } - - }else{ - //tried to access chat without logging in - val jsonError = JSONObject(); - jsonError.put("error","You must send your credential before sending anything else"); - - e.client.send(buildTextMessage(jsonError.toString())); - - } - - return; - }else if(json.has("message")){ - val chanMessages = this.messages[e.client.data["emergencyChannel"]]; - val message = Message(); - if(chanMessages != null){ - message.user = e.client.data["Username"].toString(); - message.message = json.getString("message"); - message.id = "-1"; - - var lat : Float; - var lng : Float; - - //javascript may send float as integer so we double check that - try { - lat = (json.getJSONArray("location")[0] as Double).toFloat(); - }catch(e : Exception){ - lat = (json.getJSONArray("location")[0] as Integer).toFloat(); - } - - try { - lng = (json.getJSONArray("location")[1] as Double).toFloat(); - }catch(e : Exception){ - lng = (json.getJSONArray("location")[1] as Integer).toFloat(); - } - - message.location = mutableListOf(lat,lng); - - synchronized(chanMessages,{ - chanMessages.push(Pair(e.client.data["Username"].toString(),message)) - }); - } - - var chanName = ""; - if(e.client.data["emergencyChannel"] != null){ - chanName = e.client.data["emergencyChannel"].toString(); - } - - for(c in this.clients){ - this.dispatchMessage(chanName,message,"add"); - } - }else{ - System.out.println("unknown JSON: "+json.toString()); - } - }catch (e : Exception){ - //System.out.println("Something went wrong (probably JSON parsing error"); - e.printStackTrace(); - } - } - - fun dispatchMessage(channel: String,message: Message, operation : String){ - - val authorizedOperations = listOf("add","upd","del"); - - if(!authorizedOperations.contains(operation)){ - throw Exception("Unauthorized operation"); - } - - val array = JSONObject(); - array.put(message.id,message.toJSON()) - - val jsonMessage = JSONObject(); - jsonMessage.put("error",false); - - //all operations must be present but can be empty - for (op in authorizedOperations){ - if(op == operation){ - jsonMessage.put(op,array); - }else{ - jsonMessage.put(op,JSONArray()); - } - } - - for(c in this.clients){ - //dispatch message to logged client in the right channel or in any channel if channel is an empty string (broadcast) - if(c.data["IsLogged"] == true && ((channel != "" && c.data["emergencyChannel"] == channel) || channel == "")){ - c.send(buildTextMessage(jsonMessage.toString())); - } - } - } - - fun deleteMessage(id : String){ - this.messages.keys.forEach { - val key = it; - val array = this.messages[it]; - array?.toList()?.forEach{ - if(it.second.id == id){ - array.remove(it); - val msg = Message() - msg.id = id; - this.dispatchMessage(key,msg,"del"); - } - } - } - } - - fun updateMessage(msg : Message){ - this.messages.keys.forEach { - val key = it; - val array = this.messages[it]; - var index = 0; - array?.toList()?.forEach{ - if(it.second.id == msg.id){ - msg.user = it.second.user; - msg.location = it.second.location; - msg.timestamp = it.second.timestamp; - array.set(index,Pair(it.first,msg)); - this.dispatchMessage(key,msg,"upd"); - } - index++; - } - } - } - - fun getMessages(chan : String) : MutableList>{ - val channel = this.messages[chan]?.toList(); - val returned = mutableListOf>() - if(channel != null){ - for (m in channel){ - returned.add(Pair(m.second.id,m.second)); - } - } - - return returned; - } + constructor(server: Server) : super(server); } \ No newline at end of file diff --git a/src/Channels/Event.kt b/src/Channels/Event.kt index f6d22dd..54631e8 100644 --- a/src/Channels/Event.kt +++ b/src/Channels/Event.kt @@ -1,266 +1,11 @@ package Channels -import Collections.Message -import Collections.Stack -import org.json.JSONArray -import org.json.JSONObject -import seekdasky.kWebSocket.Client -import seekdasky.kWebSocket.Event -import seekdasky.kWebSocket.Listeners.AsynchronousListener -import seekdasky.kWebSocket.Message.buildTextMessage import seekdasky.kWebSocket.Server -class Event : AsynchronousListener { +class Event : AbstractChannel { - var clients : MutableList; - val messages : MutableMap>>; - val serv : Server; + override val chanName = "event"; - constructor(serv : Server){ - this.clients = mutableListOf(); - this.messages = mutableMapOf(); - this.serv = serv; - } + constructor(server: Server) : super(server); - override fun filter(c: Client): Boolean { - val regex = "\\/event\\/(.*)".toRegex() - val result = regex.findAll(c.URL); - if(result.count() == 1){ - return true; - } - return false; - } - - override fun processClosed(e: Event) { - this.clients.remove(e.client); - ConnectChannel.notifyDisconnect(e.client); - System.out.println("A client disconnected ("+this.clients.count()+" clients connected)"); - } - - override fun processConnection(c: Client) { - this.clients.add(c); - val regex = "\\/event\\/(.*)".toRegex(); - val result = regex.findAll(c.URL).elementAt(0).groups[1]?.value ?: ""; - - //create stack if not present - if(this.messages[result] == null){ - this.messages[result] = Stack( 50); - } - - //bind client to channel - if(c.data["emergencyChannel"] == null){ - c.data["emergencyChannel"] = result; - } - c.data["IsLogged"] = false; - } - - fun manuallyDispatchMessage(channel : String, msg : Message, operation : String){ - - val channelStack = this.messages[channel]; - - if(channelStack != null){ - - synchronized(channelStack, { - channelStack.push(Pair(msg.user,msg)); - }) - - this.dispatchMessage(channel,msg,operation); - }else if (channel == ""){ - //broadcast - for(c in this.messages.values){ - synchronized(c,{ - c.push(Pair(msg.user,msg)); - }) - } - - this.dispatchMessage(channel,msg,operation); - - } - } - - override fun processEvent(e: Event) { - try{ - val json = JSONObject(e.message.getString()) - - //dead code, should remove it later - if(json.has("close")){ - return - } - - //si l'utilisateur n'est pas log, on le check - if(e.client.data["IsLogged"] != true){ - //json format : {username:xxx} - if(json.has("name") && json.getString("name") != null){ - e.client.data["Username"] = json.getString("name"); - - //if the client correctly identified with the Interop server - if(ConnectChannel.isConnected(e.client)){ - //log - System.out.println("Emergency connection ("+this.clients.count()+" clients connected)"); - - //return OK to the client - e.client.data["IsLogged"] = true; - val jsonLogin = JSONObject(); - jsonLogin.put("error",false); - e.client.send(buildTextMessage(jsonLogin.toString())); - - //give the client the list of the most recent messages - val array = JSONObject(); - - val chanMessages = this.messages[e.client.data["emergencyChannel"]]; - if(chanMessages != null){ - synchronized(chanMessages,{ - chanMessages.toList().forEach { - array.put(it.second.id,it.second.toJSON()) - } - }) - } - - //build JSON - val jsonMessage = JSONObject(); - jsonMessage.put("error",false); - jsonMessage.put("add",array); - - e.client.send(buildTextMessage(jsonMessage.toString())); - }else{ - val jsonError = JSONObject(); - jsonError.put("error","Invalid credentials"); - - e.client.send(buildTextMessage(jsonError.toString())); - } - - }else{ - //tried to access chat without logging in - val jsonError = JSONObject(); - jsonError.put("error","You must send your credential before sending anything else"); - - e.client.send(buildTextMessage(jsonError.toString())); - - } - - return; - }else if(json.has("message")){ - val chanMessages = this.messages[e.client.data["emergencyChannel"]]; - val message = Message(); - if(chanMessages != null){ - message.user = e.client.data["Username"].toString(); - message.message = json.getString("message"); - message.id = "-1"; - message.type = json.getInt("type"); - - var lat : Float; - var lng : Float; - - //javascript may send float as integer so we double check that - try { - lat = (json.getJSONArray("location")[0] as Double).toFloat(); - }catch(e : Exception){ - lat = (json.getJSONArray("location")[0] as Integer).toFloat(); - } - - try { - lng = (json.getJSONArray("location")[1] as Double).toFloat(); - }catch(e : Exception){ - lng = (json.getJSONArray("location")[1] as Integer).toFloat(); - } - - message.location = mutableListOf(lat,lng); - - synchronized(chanMessages,{ - chanMessages.push(Pair(e.client.data["Username"].toString(),message)) - }); - } - - var chanName = ""; - if(e.client.data["emergencyChannel"] != null){ - chanName = e.client.data["emergencyChannel"].toString(); - } - - for(c in this.clients){ - this.dispatchMessage(chanName,message,"add"); - } - }else{ - System.out.println("unknown JSON: "+json.toString()); - } - }catch (e : Exception){ - //System.out.println("Something went wrong (probably JSON parsing error"); - e.printStackTrace(); - } - } - - fun dispatchMessage(channel: String, message: Message, operation : String){ - - val authorizedOperations = listOf("add","upd","del"); - - if(!authorizedOperations.contains(operation)){ - throw Exception("Unauthorized operation"); - } - - val array = JSONObject(); - array.put(message.id,message.toJSON()) - - val jsonMessage = JSONObject(); - jsonMessage.put("error",false); - - //all operations must be present but can be empty - for (op in authorizedOperations){ - if(op == operation){ - jsonMessage.put(op,array); - }else{ - jsonMessage.put(op, JSONArray()); - } - } - - for(c in this.clients){ - //dispatch message to logged client in the right channel or in any channel if channel is an empty string (broadcast) - if(c.data["IsLogged"] == true && ((channel != "" && c.data["emergencyChannel"] == channel) || channel == "")){ - c.send(buildTextMessage(jsonMessage.toString())); - } - } - } - - fun deleteMessage(id : String){ - this.messages.keys.forEach { - val key = it; - val array = this.messages[it]; - array?.toList()?.forEach{ - if(it.second.id == id){ - array.remove(it); - val msg = Message() - msg.id = id; - this.dispatchMessage(key,msg,"del"); - } - } - } - } - - fun updateMessage(msg : Message){ - this.messages.keys.forEach { - val key = it; - val array = this.messages[it]; - var index = 0; - array?.toList()?.forEach{ - if(it.second.id == msg.id){ - msg.user = it.second.user; - msg.location = it.second.location; - msg.timestamp = it.second.timestamp; - array.set(index,Pair(it.first,msg)); - this.dispatchMessage(key,msg,"upd"); - } - index++; - } - } - } - - fun getMessages(chan : String) : MutableList>{ - val channel = this.messages[chan]?.toList(); - val returned = mutableListOf>() - if(channel != null){ - for (m in channel){ - returned.add(Pair(m.second.id,m.second)); - } - } - - return returned; - } } \ No newline at end of file