Skip to content
Snippets Groups Projects
Commit 553ca5d5 authored by Tobias Ullerich's avatar Tobias Ullerich
Browse files

Add basic websocket implementation for sync

parent 036618dc
Branches
No related tags found
No related merge requests found
package de.tobias.playpad.server
import java.nio.file.{Files, Paths}
import java.sql.{Driver, DriverManager}
import com.j256.ormlite.dao.{Dao, DaoManager}
import com.j256.ormlite.jdbc.JdbcConnectionSource
import com.j256.ormlite.table.TableUtils
import de.tobias.playpad.server.account.{Account, Session}
import de.tobias.playpad.server.plugin.Plugin
import de.tobias.playpad.server.server.account._
import de.tobias.playpad.server.server.plugin.{PluginGet, PluginList}
import de.tobias.playpad.server.server.project.ProjectHandler
import de.tobias.playpad.server.settings.SettingsHandler
import de.tobias.playpad.server.transformer.JsonTransformer
import spark.Spark._
......@@ -27,13 +31,21 @@ object PlayPadServer extends App {
private val settings = settingsLoader.load(settingsPath)
private val databaseUrl = "jdbc:mysql://" + settings.db_host + ":" + settings.db_port + "/" + settings.db_database
private val databaseUrl = "jdbc:mysql://" + settings.db_host + ":" + settings.db_port + "/" + settings.db_database + "?autoReconnect=true"
var connectionSource = new JdbcConnectionSource(databaseUrl)
connectionSource.setUsername(settings.db_username)
connectionSource.setPassword(settings.db_password)
val dao: Dao[Plugin, Int] = DaoManager.createDao(connectionSource, classOf[Plugin])
private val databaseConnection = DriverManager.getConnection(databaseUrl, settings.db_username, settings.db_password)
val pluginDao: Dao[Plugin, Int] = DaoManager.createDao(connectionSource, classOf[Plugin])
val accountDao: Dao[Account, Int] = DaoManager.createDao(connectionSource, classOf[Account])
val sessionDao: Dao[Session, Int] = DaoManager.createDao(connectionSource, classOf[Session])
TableUtils.createTableIfNotExists(connectionSource, classOf[Plugin])
TableUtils.createTableIfNotExists(connectionSource, classOf[Account])
TableUtils.createTableIfNotExists(connectionSource, classOf[Session])
// Setup Http Server
port(8090)
......@@ -43,10 +55,32 @@ object PlayPadServer extends App {
secure("deploy/keystore.jks", settings.keystorePassword, null, null)
get("/plugins/:id", new PluginGet(dao), new JsonTransformer)
get("/plugins", new PluginList(dao), new JsonTransformer)
// PlayWall Cloud
webSocket("/project", new ProjectHandler(sessionDao, databaseConnection))
RouteOverview.enableRouteOverview()
// Plugins
get("/plugins/:id", new PluginGet(pluginDao), new JsonTransformer)
get("/plugins", new PluginList(pluginDao), new JsonTransformer)
// Account
post("/accounts", new AccountPost(accountDao), new JsonTransformer)
put("/accounts", new AccountPut(accountDao), new JsonTransformer)
post("/sessions", new SessionPost(accountDao), new JsonTransformer)
delete("/sessions", new SessionDelete(accountDao), new JsonTransformer)
get("/sessions", new SessionGet(accountDao), new JsonTransformer)
// DEBUG
exception(classOf[Exception], (exception, _, _) => {
exception.printStackTrace()
halt(500, "internal error: " + exception.getLocalizedMessage)
})
RouteOverview.enableRouteOverview()
SettingsHandler.saver.save(settings, settingsPath)
Runtime.getRuntime.addShutdownHook(new Thread(() => {
databaseConnection.close()
stop()
}))
}
package de.tobias.playpad.server.server.project
import java.sql.Connection
import com.google.gson.{JsonObject, JsonParser}
import com.j256.ormlite.dao.Dao
import com.sun.xml.internal.bind.v2.model.core.ID
import de.tobias.playpad.server.account
import de.tobias.playpad.server.account.Account
import org.eclipse.jetty.websocket.api.Session
import org.eclipse.jetty.websocket.api.annotations.{OnWebSocketClose, OnWebSocketConnect, OnWebSocketMessage, WebSocket}
import scala.collection.{Map, mutable}
/**
* Created by tobias on 13.02.17.
*/
@WebSocket class ProjectHandler(sessionDao: Dao[account.Session, Int], connection: Connection) {
// TODO mutable.HashSet --> Set
private var sessions: Map[Account, mutable.HashSet[Session]] = new mutable.HashMap[Account, mutable.HashSet[Session]]()
@OnWebSocketConnect def onConnect(serverSession: Session): Unit = {
val key = serverSession.getUpgradeRequest.getHeader("key")
if (key == null) {
serverSession.close(500, "Invalid Key")
}
val sessions = sessionDao.queryForEq("key", key)
if (sessions.size() == 1) {
val session = sessions.get(0)
if (!this.sessions.contains(session.getAccount)) {
this.sessions += (session.getAccount -> new mutable.HashSet[Session]())
}
this.sessions(session.getAccount) += serverSession
} else {
serverSession.close(500, "Invalid Key")
}
}
@OnWebSocketClose def onClose(serverSession: Session, status: Int, reason: String): Unit = {
val key = serverSession.getUpgradeRequest.getHeader("key")
if (key == null) {
serverSession.close(500, "Invalid Key")
}
val sessions = sessionDao.queryForEq("key", key)
if (sessions.size() == 1) {
val session = sessions.get(0)
this.sessions(session.getAccount) -= serverSession
}
}
@OnWebSocketMessage def onMessage(serverSession: Session, text: String): Unit = {
// Store in Database
try {
val json = new JsonParser().parse(text)
json match {
case jsonObject: JsonObject =>
val className = jsonObject.get("class").getAsString
val field = jsonObject.get("field").getAsString
val id = jsonObject.get("id").getAsString
val sql = "INSERT INTO " + className + " (id, " + field + ") VALUES(?, ?) " +
"ON DUPLICATE KEY UPDATE " + field + "=?"
val preparedStatement = connection.prepareStatement(sql)
preparedStatement.setString(1, id)
val valueType = Class.forName(jsonObject.get("type").getAsString)
if (valueType == classOf[String]) {
val value = jsonObject.get("value").getAsString
preparedStatement.setString(2, value)
preparedStatement.setString(3, value)
} else if (valueType == classOf[Boolean]) {
val value = jsonObject.get("value").getAsBoolean
preparedStatement.setBoolean(2, value)
preparedStatement.setBoolean(3, value)
} else if (valueType == classOf[Integer]){
val value = jsonObject.get("value").getAsInt
preparedStatement.setInt(2, value)
preparedStatement.setInt(3, value)
} else if (valueType == classOf[Double]){
val value = jsonObject.get("value").getAsDouble
preparedStatement.setDouble(2, value)
preparedStatement.setDouble(3, value)
}
preparedStatement.execute()
preparedStatement.close()
case _ =>
}
// Push to clients
val key = serverSession.getUpgradeRequest.getHeader("key")
if (key == null) {
serverSession.close(500, "Invalid Key")
}
val sessions = sessionDao.queryForEq("key", key)
if (sessions.size() == 1) {
val session = sessions.get(0)
this.sessions(session.getAccount)
.filter(s => s != serverSession)
.foreach(s => s.getRemote.sendStringByFuture(text))
}
} catch {
case e: Exception => e.printStackTrace()
}
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment