mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-09 06:55:54 +01:00
Add prototype of global action support
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import _root_.servlet.{BasicAuthenticationFilter, TransactionFilter}
|
import _root_.servlet.{BasicAuthenticationFilter, TransactionFilter, PluginActionFilter}
|
||||||
import app._
|
import app._
|
||||||
//import jp.sf.amateras.scalatra.forms.ValidationJavaScriptProvider
|
//import jp.sf.amateras.scalatra.forms.ValidationJavaScriptProvider
|
||||||
import org.scalatra._
|
import org.scalatra._
|
||||||
@@ -12,6 +12,8 @@ class ScalatraBootstrap extends LifeCycle {
|
|||||||
context.getFilterRegistration("transactionFilter").addMappingForUrlPatterns(EnumSet.allOf(classOf[DispatcherType]), true, "/*")
|
context.getFilterRegistration("transactionFilter").addMappingForUrlPatterns(EnumSet.allOf(classOf[DispatcherType]), true, "/*")
|
||||||
context.addFilter("basicAuthenticationFilter", new BasicAuthenticationFilter)
|
context.addFilter("basicAuthenticationFilter", new BasicAuthenticationFilter)
|
||||||
context.getFilterRegistration("basicAuthenticationFilter").addMappingForUrlPatterns(EnumSet.allOf(classOf[DispatcherType]), true, "/git/*")
|
context.getFilterRegistration("basicAuthenticationFilter").addMappingForUrlPatterns(EnumSet.allOf(classOf[DispatcherType]), true, "/git/*")
|
||||||
|
context.addFilter("pluginActionFilter", new PluginActionFilter)
|
||||||
|
context.getFilterRegistration("pluginActionFilter").addMappingForUrlPatterns(EnumSet.allOf(classOf[DispatcherType]), true, "/*")
|
||||||
|
|
||||||
// Register controllers
|
// Register controllers
|
||||||
context.mount(new AnonymousAccessController, "/*")
|
context.mount(new AnonymousAccessController, "/*")
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ package plugin
|
|||||||
|
|
||||||
import java.io.{FilenameFilter, File}
|
import java.io.{FilenameFilter, File}
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
|
import javax.servlet.http.{HttpServletRequest, HttpServletResponse}
|
||||||
|
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
|
import service.RepositoryService.RepositoryInfo
|
||||||
import util.Directory._
|
import util.Directory._
|
||||||
|
import util.JDBCUtil._
|
||||||
|
|
||||||
import scala.collection.mutable.ListBuffer
|
import scala.collection.mutable.ListBuffer
|
||||||
|
|
||||||
@@ -12,6 +15,8 @@ class PluginRegistry {
|
|||||||
|
|
||||||
private val plugins = new ListBuffer[PluginInfo]
|
private val plugins = new ListBuffer[PluginInfo]
|
||||||
private val javaScripts = new ListBuffer[(String, String)]
|
private val javaScripts = new ListBuffer[(String, String)]
|
||||||
|
private val globalActions = new ListBuffer[GlobalAction]
|
||||||
|
private val repositoryActions = new ListBuffer[RepositoryAction]
|
||||||
|
|
||||||
def addPlugin(pluginInfo: PluginInfo): Unit = {
|
def addPlugin(pluginInfo: PluginInfo): Unit = {
|
||||||
plugins += pluginInfo
|
plugins += pluginInfo
|
||||||
@@ -19,17 +24,51 @@ class PluginRegistry {
|
|||||||
|
|
||||||
def getPlugins(): List[PluginInfo] = plugins.toList
|
def getPlugins(): List[PluginInfo] = plugins.toList
|
||||||
|
|
||||||
|
def addGlobalAction(method: String, path: String)(f: (HttpServletRequest, HttpServletResponse) => Any): Unit = {
|
||||||
|
globalActions += GlobalAction(method.toLowerCase, path, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
//def getGlobalActions(): List[GlobalAction] = globalActions.toList
|
||||||
|
|
||||||
|
def getGlobalAction(method: String, path: String): Option[(HttpServletRequest, HttpServletResponse) => Any] = {
|
||||||
|
globalActions.find { globalAction =>
|
||||||
|
globalAction.method == method.toLowerCase && path.matches(globalAction.path)
|
||||||
|
}.map(_.function)
|
||||||
|
}
|
||||||
|
|
||||||
|
def addRepositoryAction(method: String, path: String)(f: (HttpServletRequest, HttpServletResponse, RepositoryInfo) => Any): Unit = {
|
||||||
|
repositoryActions += RepositoryAction(method.toLowerCase, path, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
//def getRepositoryActions(): List[RepositoryAction] = repositoryActions.toList
|
||||||
|
|
||||||
|
def getRepositoryAction(method: String, path: String): Option[(HttpServletRequest, HttpServletResponse, RepositoryInfo) => Any] = {
|
||||||
|
// TODO
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
def addJavaScript(path: String, script: String): Unit = {
|
def addJavaScript(path: String, script: String): Unit = {
|
||||||
javaScripts += Tuple2(path, script)
|
javaScripts += Tuple2(path, script)
|
||||||
}
|
}
|
||||||
|
|
||||||
def getJavaScripts(): List[(String, String)] = javaScripts.toList
|
//def getJavaScripts(): List[(String, String)] = javaScripts.toList
|
||||||
|
|
||||||
def getJavaScript(currentPath: String): Option[String] = {
|
def getJavaScript(currentPath: String): Option[String] = {
|
||||||
println(currentPath)
|
javaScripts.find(x => currentPath.matches(x._1)).map(_._2)
|
||||||
getJavaScripts().find(x => currentPath.matches(x._1)).map(_._2)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private case class GlobalAction(
|
||||||
|
method: String,
|
||||||
|
path: String,
|
||||||
|
function: (HttpServletRequest, HttpServletResponse) => Any
|
||||||
|
)
|
||||||
|
|
||||||
|
private case class RepositoryAction(
|
||||||
|
method: String,
|
||||||
|
path: String,
|
||||||
|
function: (HttpServletRequest, HttpServletResponse, RepositoryInfo) => Any
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object PluginRegistry {
|
object PluginRegistry {
|
||||||
@@ -40,24 +79,37 @@ object PluginRegistry {
|
|||||||
|
|
||||||
def apply(): PluginRegistry = instance
|
def apply(): PluginRegistry = instance
|
||||||
|
|
||||||
def initialize(): Unit = {
|
def initialize(conn: java.sql.Connection): Unit = {
|
||||||
new File(PluginHome).listFiles(new FilenameFilter {
|
val pluginDir = new File(PluginHome)
|
||||||
override def accept(dir: File, name: String): Boolean = name.endsWith(".jar")
|
if(pluginDir.exists && pluginDir.isDirectory){
|
||||||
}).foreach { pluginJar =>
|
pluginDir.listFiles(new FilenameFilter {
|
||||||
val classLoader = new URLClassLoader(Array(pluginJar.toURI.toURL), Thread.currentThread.getContextClassLoader)
|
override def accept(dir: File, name: String): Boolean = name.endsWith(".jar")
|
||||||
try {
|
}).foreach { pluginJar =>
|
||||||
val plugin = classLoader.loadClass("Plugin").newInstance().asInstanceOf[Plugin]
|
val classLoader = new URLClassLoader(Array(pluginJar.toURI.toURL), Thread.currentThread.getContextClassLoader)
|
||||||
plugin.initialize(instance)
|
try {
|
||||||
instance.addPlugin(PluginInfo(
|
val plugin = classLoader.loadClass("Plugin").newInstance().asInstanceOf[Plugin]
|
||||||
pluginId = plugin.pluginId,
|
plugin.initialize(instance)
|
||||||
pluginName = plugin.pluginName,
|
instance.addPlugin(PluginInfo(
|
||||||
version = plugin.version,
|
pluginId = plugin.pluginId,
|
||||||
description = plugin.description,
|
pluginName = plugin.pluginName,
|
||||||
pluginClass = plugin
|
version = plugin.version,
|
||||||
))
|
description = plugin.description,
|
||||||
} catch {
|
pluginClass = plugin
|
||||||
case e: Exception => {
|
))
|
||||||
logger.error(s"Error during plugin initialization", e)
|
|
||||||
|
conn.find("SELECT * FROM PLUGIN WHERE PLUGIN_ID = ?", plugin.pluginId)(_.getString("VERSION")) match {
|
||||||
|
// Update if the plugin is already registered
|
||||||
|
case Some(currentVersion) => conn.update("UPDATE PLUGIN SET VERSION = ? WHERE PLUGIN_ID = ?", plugin.version, plugin.pluginId)
|
||||||
|
// Insert if the plugin does not exist
|
||||||
|
case None => conn.update("INSERT INTO PLUGIN (PLUGIN_ID, VERSION) VALUES (?, ?)", plugin.pluginId, plugin.version)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Migration
|
||||||
|
|
||||||
|
} catch {
|
||||||
|
case e: Exception => {
|
||||||
|
logger.error(s"Error during plugin initialization", e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import org.eclipse.jgit.api.Git
|
|||||||
import util.Directory
|
import util.Directory
|
||||||
import plugin._
|
import plugin._
|
||||||
|
|
||||||
|
import scala.slick.jdbc.meta.MBestRowIdentifierColumn.Scope.Session
|
||||||
|
|
||||||
object AutoUpdate {
|
object AutoUpdate {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -103,8 +105,10 @@ object AutoUpdate {
|
|||||||
conn.update("UPDATE ACTIVITY SET ADDITIONAL_INFO = ? WHERE ACTIVITY_ID = ?", newInfo, rs.getInt("ACTIVITY_ID"))
|
conn.update("UPDATE ACTIVITY SET ADDITIONAL_INFO = ? WHERE ACTIVITY_ID = ?", newInfo, rs.getInt("ACTIVITY_ID"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FileUtils.deleteDirectory(Directory.getPluginCacheDir())
|
ignore {
|
||||||
FileUtils.deleteDirectory(new File(Directory.PluginHome))
|
FileUtils.deleteDirectory(Directory.getPluginCacheDir())
|
||||||
|
//FileUtils.deleteDirectory(new File(Directory.PluginHome))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new Version(2, 2),
|
new Version(2, 2),
|
||||||
@@ -235,10 +239,12 @@ class AutoUpdateListener extends ServletContextListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.debug("End schema update")
|
logger.debug("End schema update")
|
||||||
|
|
||||||
|
// Load plugins
|
||||||
|
|
||||||
|
PluginRegistry.initialize(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load plugins
|
|
||||||
PluginRegistry.initialize()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def contextDestroyed(sce: ServletContextEvent): Unit = {
|
def contextDestroyed(sce: ServletContextEvent): Unit = {
|
||||||
|
|||||||
38
src/main/scala/servlet/PluginActionFilter.scala
Normal file
38
src/main/scala/servlet/PluginActionFilter.scala
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package servlet
|
||||||
|
|
||||||
|
import javax.servlet._
|
||||||
|
import javax.servlet.http.{HttpServletResponse, HttpServletRequest}
|
||||||
|
|
||||||
|
import play.twirl.api.Html
|
||||||
|
import plugin.PluginRegistry
|
||||||
|
|
||||||
|
class PluginActionFilter extends Filter {
|
||||||
|
|
||||||
|
def init(config: FilterConfig) = {}
|
||||||
|
|
||||||
|
def destroy(): Unit = {}
|
||||||
|
|
||||||
|
def doFilter(req: ServletRequest, res: ServletResponse, chain: FilterChain): Unit = (req, res) match {
|
||||||
|
case (req: HttpServletRequest, res: HttpServletResponse) => {
|
||||||
|
val method = req.getMethod.toLowerCase
|
||||||
|
val path = req.getRequestURI.substring(req.getContextPath.length)
|
||||||
|
val registry = PluginRegistry()
|
||||||
|
registry.getGlobalAction(method, path).map { action =>
|
||||||
|
action(req, res) match {
|
||||||
|
// TODO to be type classes?
|
||||||
|
case x: String =>
|
||||||
|
res.setContentType("text/plain; charset=UTF-8")
|
||||||
|
res.getWriter.write(x)
|
||||||
|
res.getWriter.flush()
|
||||||
|
case x: Html =>
|
||||||
|
res.setContentType("text/html; charset=UTF-8")
|
||||||
|
res.getWriter.write(x.body)
|
||||||
|
res.getWriter.flush()
|
||||||
|
}
|
||||||
|
}.getOrElse {
|
||||||
|
chain.doFilter(req, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -37,4 +37,10 @@ object ControlUtil {
|
|||||||
def using[T](treeWalk: TreeWalk)(f: TreeWalk => T): T =
|
def using[T](treeWalk: TreeWalk)(f: TreeWalk => T): T =
|
||||||
try f(treeWalk) finally treeWalk.release()
|
try f(treeWalk) finally treeWalk.release()
|
||||||
|
|
||||||
|
def ignore[T](f: => Unit): Unit = try {
|
||||||
|
f
|
||||||
|
} catch {
|
||||||
|
case e: Exception => ()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,14 @@ object JDBCUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def find[T](sql: String, params: Any*)(f: ResultSet => T): Option[T] = {
|
||||||
|
execute(sql, params: _*){ stmt =>
|
||||||
|
using(stmt.executeQuery()){ rs =>
|
||||||
|
if(rs.next) Some(f(rs)) else None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def select[T](sql: String, params: Any*)(f: ResultSet => T): Seq[T] = {
|
def select[T](sql: String, params: Any*)(f: ResultSet => T): Seq[T] = {
|
||||||
execute(sql, params: _*){ stmt =>
|
execute(sql, params: _*){ stmt =>
|
||||||
using(stmt.executeQuery()){ rs =>
|
using(stmt.executeQuery()){ rs =>
|
||||||
|
|||||||
Reference in New Issue
Block a user