(refs #32)Add JavaScript API

This commit is contained in:
Naoki Takezoe
2014-06-08 00:37:01 +09:00
parent daf5fc434c
commit 378c2c39a8
3 changed files with 50 additions and 16 deletions

View File

@@ -3,40 +3,71 @@ package plugin
import app.Context import app.Context
import javax.servlet.http.{HttpServletResponse, HttpServletRequest} import javax.servlet.http.{HttpServletResponse, HttpServletRequest}
import javax.script.ScriptEngineManager import javax.script.ScriptEngineManager
import scala.collection.mutable.ListBuffer
import org.slf4j.LoggerFactory
import jdk.nashorn.api.scripting.ScriptObjectMirror
/** /**
* Provides extension points to plug-ins. * Provides extension points to plug-ins.
*/ */
object PluginSystem { object PluginSystem {
private val repositoryMenuList = scala.collection.mutable.ListBuffer[RepositoryMenu]() private val logger = LoggerFactory.getLogger(PluginSystem.getClass)
private val globalMenuList = scala.collection.mutable.ListBuffer[GlobalMenu]()
private val actionList = scala.collection.mutable.ListBuffer[Action]() private val repositoryMenuList = ListBuffer[RepositoryMenu]()
private val globalMenuList = ListBuffer[GlobalMenu]()
private val repositoryActionList = ListBuffer[Action]()
private val globalActionList = ListBuffer[Action]()
case class GlobalMenu(label: String, url: String, icon: String, condition: Context => Boolean) case class GlobalMenu(label: String, url: String, icon: String, condition: Context => Boolean)
case class RepositoryMenu(label: String, name: String, url: String, icon: String, condition: Context => Boolean) case class RepositoryMenu(label: String, name: String, url: String, icon: String, condition: Context => Boolean)
case class Action(path: String, function: (HttpServletRequest, HttpServletResponse) => Any) case class Action(path: String, function: (HttpServletRequest, HttpServletResponse) => Any)
def addRepositoryMenu(label: String, name: String, url: String, icon: String = "")(condition: Context => Boolean): Unit = { def addRepositoryMenu(label: String, name: String, url: String, icon: String)(condition: Context => Boolean): Unit = {
repositoryMenuList += RepositoryMenu(label, name, url, icon, condition) repositoryMenuList += RepositoryMenu(label, name, url, icon, condition)
} }
def addGlobalMenu(label: String, url: String, icon: String = "")(condition: Context => Boolean): Unit = { def addRepositoryMenu(label: String, name: String, url: String, icon: String, condition: ScriptObjectMirror): Unit = {
repositoryMenuList += RepositoryMenu(label, name, url, icon, (context) => condition.call(this, context).asInstanceOf[Boolean])
}
def addGlobalMenu(label: String, url: String, icon: String)(condition: Context => Boolean): Unit = {
globalMenuList += GlobalMenu(label, url, icon, condition) globalMenuList += GlobalMenu(label, url, icon, condition)
} }
def addAction(path: String)(function: (HttpServletRequest, HttpServletResponse) => Any): Unit = { def addGlobalMenu(label: String, url: String, icon: String, condition: ScriptObjectMirror): Unit = {
actionList += Action(path, function) globalMenuList += GlobalMenu(label, url, icon, (context) => condition.call(this, context).asInstanceOf[Boolean])
}
def addGlobalAction(path: String)(function: (HttpServletRequest, HttpServletResponse) => Any): Unit = {
globalActionList += Action(path, function)
}
def addGlobalAction(path: String, function: ScriptObjectMirror): Unit = {
globalActionList += Action(path, (request, response) => function.call(this, request, response))
}
def addRepositoryAction(path: String)(function: (HttpServletRequest, HttpServletResponse) => Any): Unit = {
repositoryActionList += Action(path, function)
}
def addRepositoryAction(path: String, function: ScriptObjectMirror): Unit = {
repositoryActionList += Action(path, (request, response) => function.call(this, request, response))
} }
def evaluateJavaScript(script: String): Any = { def evaluateJavaScript(script: String): Any = {
val engine = new ScriptEngineManager().getEngineByName("JavaScript") val engine = new ScriptEngineManager().getEngineByName("JavaScript")
engine.eval(script) logger.debug("Script: " + script)
engine.put("PluginSystem", this)
val result = engine.eval(script)
logger.debug("Result: " + result)
result
} }
lazy val repositoryMenus: List[RepositoryMenu] = repositoryMenuList.toList def repositoryMenus: List[RepositoryMenu] = repositoryMenuList.toList
lazy val globalMenus: List[GlobalMenu] = globalMenuList.toList def globalMenus: List[GlobalMenu] = globalMenuList.toList
lazy val actions: List[Action] = actionList.toList def repositoryActions: List[Action] = repositoryActionList.toList
def globalActions: List[Action] = globalActionList.toList
// TODO This is a test // TODO This is a test
addGlobalMenu("Google", "http://www.google.co.jp/", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAEvwAABL8BkeKJvAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAIgSURBVEiJtdZNiI1hFAfw36ORhSFFPgYLszOKJAsWRLGzks1gYyFZKFs7C7K2Y2XDRiwmq9kIJWQjJR9Tk48xRtTIRwjH4p473nm99yLNqdNTz/mf//+555x7ektEmEmbNaPs6OkUKKX0YBmWp6/IE8bwIs8xjEfEt0aiiJBl6sEuXMRLfEf8pX/PnIvJ0TPFWxE4+w+Ef/Kzbd5qDx5l8H8tkku7LG17gH7sxWatevdhEUoXsjda5RnDTZzH6jagtMe0lHIa23AJw3iOiSRZlmJ9mfcyfTzFl2AldmI3rkbEkbrAYKrX7S1eVRyWVnxhQ87eiLjQ+o2/mtyve+PuYy3W4+EfsP2/TVGKTHRI+Iz9Fdx8XOmAnZjGWRMYqoF/4ESW4hpOYk1iZ2WsLjDUTeBYBfgeuyux2XiNT5hXud+DD5W8Y90EtifoSfultfjx7MVtrKzcr8No5m7vJtCLx1hQJ8/4IZzClpyoy5ibsYUYQW81Z9o2jYgPeKr15+poEXE9+1XF9WIkOaasaV2P4k4pZUdDbEm+VEQcjIgtEfGxlLIVd/Gs6TX1MhzQquU3HK1t23f4IsuS94fxNXMO/MbXIDBg+tidw5yMbcCmylSdqWEH/kagYLKWeAt9Fcxi3KhhJuXq6SqQBMO15NDalvswmLWux4cbuToIbMS9BpJOfg8bm7imtmmTlVJWaa3hpnU9nufziBjtyDHTny0/AaA7Qnb4AM4aAAAAAElFTkSuQmCC") addGlobalMenu("Google", "http://www.google.co.jp/", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAEvwAABL8BkeKJvAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAIgSURBVEiJtdZNiI1hFAfw36ORhSFFPgYLszOKJAsWRLGzks1gYyFZKFs7C7K2Y2XDRiwmq9kIJWQjJR9Tk48xRtTIRwjH4p473nm99yLNqdNTz/mf//+555x7ektEmEmbNaPs6OkUKKX0YBmWp6/IE8bwIs8xjEfEt0aiiJBl6sEuXMRLfEf8pX/PnIvJ0TPFWxE4+w+Ef/Kzbd5qDx5l8H8tkku7LG17gH7sxWatevdhEUoXsjda5RnDTZzH6jagtMe0lHIa23AJw3iOiSRZlmJ9mfcyfTzFl2AldmI3rkbEkbrAYKrX7S1eVRyWVnxhQ87eiLjQ+o2/mtyve+PuYy3W4+EfsP2/TVGKTHRI+Iz9Fdx8XOmAnZjGWRMYqoF/4ESW4hpOYk1iZ2WsLjDUTeBYBfgeuyux2XiNT5hXud+DD5W8Y90EtifoSfultfjx7MVtrKzcr8No5m7vJtCLx1hQJ8/4IZzClpyoy5ibsYUYQW81Z9o2jYgPeKr15+poEXE9+1XF9WIkOaasaV2P4k4pZUdDbEm+VEQcjIgtEfGxlLIVd/Gs6TX1MhzQquU3HK1t23f4IsuS94fxNXMO/MbXIDBg+tidw5yMbcCmylSdqWEH/kagYLKWeAt9Fcxi3KhhJuXq6SqQBMO15NDalvswmLWux4cbuToIbMS9BpJOfg8bm7imtmmTlVJWaa3hpnU9nufziBjtyDHTny0/AaA7Qnb4AM4aAAAAAElFTkSuQmCC")
@@ -45,7 +76,7 @@ object PluginSystem {
addRepositoryMenu("Board", "board", "/board", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAEvwAABL8BkeKJvAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAIgSURBVEiJtdZNiI1hFAfw36ORhSFFPgYLszOKJAsWRLGzks1gYyFZKFs7C7K2Y2XDRiwmq9kIJWQjJR9Tk48xRtTIRwjH4p473nm99yLNqdNTz/mf//+555x7ektEmEmbNaPs6OkUKKX0YBmWp6/IE8bwIs8xjEfEt0aiiJBl6sEuXMRLfEf8pX/PnIvJ0TPFWxE4+w+Ef/Kzbd5qDx5l8H8tkku7LG17gH7sxWatevdhEUoXsjda5RnDTZzH6jagtMe0lHIa23AJw3iOiSRZlmJ9mfcyfTzFl2AldmI3rkbEkbrAYKrX7S1eVRyWVnxhQ87eiLjQ+o2/mtyve+PuYy3W4+EfsP2/TVGKTHRI+Iz9Fdx8XOmAnZjGWRMYqoF/4ESW4hpOYk1iZ2WsLjDUTeBYBfgeuyux2XiNT5hXud+DD5W8Y90EtifoSfultfjx7MVtrKzcr8No5m7vJtCLx1hQJ8/4IZzClpyoy5ibsYUYQW81Z9o2jYgPeKr15+poEXE9+1XF9WIkOaasaV2P4k4pZUdDbEm+VEQcjIgtEfGxlLIVd/Gs6TX1MhzQquU3HK1t23f4IsuS94fxNXMO/MbXIDBg+tidw5yMbcCmylSdqWEH/kagYLKWeAt9Fcxi3KhhJuXq6SqQBMO15NDalvswmLWux4cbuToIbMS9BpJOfg8bm7imtmmTlVJWaa3hpnU9nufziBjtyDHTny0/AaA7Qnb4AM4aAAAAAElFTkSuQmCC") addRepositoryMenu("Board", "board", "/board", "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAEvwAABL8BkeKJvAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAIgSURBVEiJtdZNiI1hFAfw36ORhSFFPgYLszOKJAsWRLGzks1gYyFZKFs7C7K2Y2XDRiwmq9kIJWQjJR9Tk48xRtTIRwjH4p473nm99yLNqdNTz/mf//+555x7ektEmEmbNaPs6OkUKKX0YBmWp6/IE8bwIs8xjEfEt0aiiJBl6sEuXMRLfEf8pX/PnIvJ0TPFWxE4+w+Ef/Kzbd5qDx5l8H8tkku7LG17gH7sxWatevdhEUoXsjda5RnDTZzH6jagtMe0lHIa23AJw3iOiSRZlmJ9mfcyfTzFl2AldmI3rkbEkbrAYKrX7S1eVRyWVnxhQ87eiLjQ+o2/mtyve+PuYy3W4+EfsP2/TVGKTHRI+Iz9Fdx8XOmAnZjGWRMYqoF/4ESW4hpOYk1iZ2WsLjDUTeBYBfgeuyux2XiNT5hXud+DD5W8Y90EtifoSfultfjx7MVtrKzcr8No5m7vJtCLx1hQJ8/4IZzClpyoy5ibsYUYQW81Z9o2jYgPeKr15+poEXE9+1XF9WIkOaasaV2P4k4pZUdDbEm+VEQcjIgtEfGxlLIVd/Gs6TX1MhzQquU3HK1t23f4IsuS94fxNXMO/MbXIDBg+tidw5yMbcCmylSdqWEH/kagYLKWeAt9Fcxi3KhhJuXq6SqQBMO15NDalvswmLWux4cbuToIbMS9BpJOfg8bm7imtmmTlVJWaa3hpnU9nufziBjtyDHTny0/AaA7Qnb4AM4aAAAAAElFTkSuQmCC")
{ context => true} { context => true}
addAction("/hello"){ (request, response) => addGlobalAction("/hello"){ (request, response) =>
"Hello World!" "Hello World!"
} }

View File

@@ -18,7 +18,7 @@ class PluginActionInvokeFilter extends Filter with SystemSettingsService {
(req, res) match { (req, res) match {
case (request: HttpServletRequest, response: HttpServletResponse) => { case (request: HttpServletRequest, response: HttpServletResponse) => {
val path = req.asInstanceOf[HttpServletRequest].getRequestURI val path = req.asInstanceOf[HttpServletRequest].getRequestURI
val action = plugin.PluginSystem.actions.find(_.path == path) val action = plugin.PluginSystem.globalActions.find(_.path == path)
if(action.isDefined){ if(action.isDefined){
val result = action.get.function(request, response) val result = action.get.function(request, response)

View File

@@ -3,7 +3,7 @@
@import view.helpers._ @import view.helpers._
@html.main("JavaScript Console"){ @html.main("JavaScript Console"){
@menu("script"){ @menu("script"){
<form action="@path/admin/script" method="POST"> <form method="POST">
<div class="box"> <div class="box">
<div class="box-header">JavaScript Console</div> <div class="box-header">JavaScript Console</div>
<div class="box-content"> <div class="box-content">
@@ -11,7 +11,7 @@
</div> </div>
</div> </div>
<fieldset> <fieldset>
<input type="submit" id="evaluate" class="btn btn-success" value="Evaluate"/> <input type="button" id="evaluate" class="btn btn-success" value="Evaluate"/>
</fieldset> </fieldset>
</form> </form>
} }
@@ -21,12 +21,15 @@
$(function(){ $(function(){
var editor = ace.edit("editor"); var editor = ace.edit("editor");
editor.setTheme("ace/theme/monokai"); editor.setTheme("ace/theme/monokai");
editor.getSession().setMode("ace/mode/javascript");
$('#evaluate').click(function(){ $('#evaluate').click(function(){
$.post('@path/admin/script', { $.post('@path/admin/script', {
script: editor.getValue() script: editor.getValue()
}, function(data){ }, function(data){
console.log(data); alert('Success: ' + data);
}).fail(function(error){
alert(error.statusText);
}); });
}); });
}); });