mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-08 22:45:51 +01:00
Plug-in action to be Scalatra controller
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
import _root_.servlet.{BasicAuthenticationFilter, TransactionFilter, PluginActionFilter}
|
import _root_.servlet.{BasicAuthenticationFilter, TransactionFilter}
|
||||||
import app._
|
import app._
|
||||||
|
import plugin.PluginRegistry
|
||||||
|
|
||||||
//import jp.sf.amateras.scalatra.forms.ValidationJavaScriptProvider
|
//import jp.sf.amateras.scalatra.forms.ValidationJavaScriptProvider
|
||||||
import org.scalatra._
|
import org.scalatra._
|
||||||
import javax.servlet._
|
import javax.servlet._
|
||||||
@@ -12,8 +14,6 @@ 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, "/*")
|
||||||
@@ -24,6 +24,11 @@ class ScalatraBootstrap extends LifeCycle {
|
|||||||
context.mount(new UserManagementController, "/*")
|
context.mount(new UserManagementController, "/*")
|
||||||
context.mount(new SystemSettingsController, "/*")
|
context.mount(new SystemSettingsController, "/*")
|
||||||
context.mount(new AccountController, "/*")
|
context.mount(new AccountController, "/*")
|
||||||
|
|
||||||
|
PluginRegistry().getControllers.foreach { case (controller, path) =>
|
||||||
|
context.mount(controller, path)
|
||||||
|
}
|
||||||
|
|
||||||
context.mount(new RepositoryViewerController, "/*")
|
context.mount(new RepositoryViewerController, "/*")
|
||||||
context.mount(new WikiController, "/*")
|
context.mount(new WikiController, "/*")
|
||||||
context.mount(new LabelsController, "/*")
|
context.mount(new LabelsController, "/*")
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package plugin
|
package plugin
|
||||||
|
|
||||||
|
import javax.servlet.ServletContext
|
||||||
|
|
||||||
import util.Version
|
import util.Version
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package plugin
|
|||||||
|
|
||||||
import java.io.{FilenameFilter, File}
|
import java.io.{FilenameFilter, File}
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
|
import javax.servlet.ServletContext
|
||||||
import javax.servlet.http.{HttpServletRequest, HttpServletResponse}
|
import javax.servlet.http.{HttpServletRequest, HttpServletResponse}
|
||||||
|
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
@@ -11,14 +12,13 @@ import util.JDBCUtil._
|
|||||||
import util.{Version, Versions}
|
import util.{Version, Versions}
|
||||||
|
|
||||||
import scala.collection.mutable.ListBuffer
|
import scala.collection.mutable.ListBuffer
|
||||||
import app.Context
|
import app.{ControllerBase, Context}
|
||||||
|
|
||||||
class PluginRegistry {
|
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 controllers = new ListBuffer[(ControllerBase, String)]
|
||||||
private val repositoryActions = new ListBuffer[RepositoryAction]
|
|
||||||
|
|
||||||
def addPlugin(pluginInfo: PluginInfo): Unit = {
|
def addPlugin(pluginInfo: PluginInfo): Unit = {
|
||||||
plugins += pluginInfo
|
plugins += pluginInfo
|
||||||
@@ -26,28 +26,11 @@ class PluginRegistry {
|
|||||||
|
|
||||||
def getPlugins(): List[PluginInfo] = plugins.toList
|
def getPlugins(): List[PluginInfo] = plugins.toList
|
||||||
|
|
||||||
def addGlobalAction(method: String, path: String)(f: (HttpServletRequest, HttpServletResponse, Context) => Any): Unit = {
|
def addController(controller: ControllerBase, path: String): Unit = {
|
||||||
globalActions += GlobalAction(method.toLowerCase, path, f)
|
controllers += ((controller, path))
|
||||||
}
|
}
|
||||||
|
|
||||||
//def getGlobalActions(): List[GlobalAction] = globalActions.toList
|
def getControllers(): List[(ControllerBase, String)] = controllers.toList
|
||||||
|
|
||||||
def getGlobalAction(method: String, path: String): Option[(HttpServletRequest, HttpServletResponse, Context) => Any] = {
|
|
||||||
globalActions.find { globalAction =>
|
|
||||||
globalAction.method == method.toLowerCase && path.matches(globalAction.path)
|
|
||||||
}.map(_.function)
|
|
||||||
}
|
|
||||||
|
|
||||||
def addRepositoryAction(method: String, path: String)(f: (HttpServletRequest, HttpServletResponse, Context, RepositoryInfo) => Any): Unit = {
|
|
||||||
repositoryActions += RepositoryAction(method.toLowerCase, path, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
//def getRepositoryActions(): List[RepositoryAction] = repositoryActions.toList
|
|
||||||
|
|
||||||
def getRepositoryAction(method: String, path: String): Option[(HttpServletRequest, HttpServletResponse, Context, 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)
|
||||||
@@ -90,7 +73,7 @@ object PluginRegistry {
|
|||||||
/**
|
/**
|
||||||
* Initializes all installed plugins.
|
* Initializes all installed plugins.
|
||||||
*/
|
*/
|
||||||
def initialize(conn: java.sql.Connection): Unit = {
|
def initialize(context: ServletContext, conn: java.sql.Connection): Unit = {
|
||||||
val pluginDir = new File(PluginHome)
|
val pluginDir = new File(PluginHome)
|
||||||
if(pluginDir.exists && pluginDir.isDirectory){
|
if(pluginDir.exists && pluginDir.isDirectory){
|
||||||
pluginDir.listFiles(new FilenameFilter {
|
pluginDir.listFiles(new FilenameFilter {
|
||||||
@@ -138,7 +121,7 @@ object PluginRegistry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def shutdown(): Unit = {
|
def shutdown(context: ServletContext): Unit = {
|
||||||
instance.getPlugins().foreach { pluginInfo =>
|
instance.getPlugins().foreach { pluginInfo =>
|
||||||
try {
|
try {
|
||||||
pluginInfo.pluginClass.shutdown(instance)
|
pluginInfo.pluginClass.shutdown(instance)
|
||||||
|
|||||||
@@ -162,12 +162,13 @@ object AutoUpdate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update database schema automatically in the context initializing.
|
* Initialize GitBucket system.
|
||||||
|
* Update database schema and load plug-ins automatically in the context initializing.
|
||||||
*/
|
*/
|
||||||
class AutoUpdateListener extends ServletContextListener {
|
class InitializeListener extends ServletContextListener {
|
||||||
import AutoUpdate._
|
import AutoUpdate._
|
||||||
|
|
||||||
private val logger = LoggerFactory.getLogger(classOf[AutoUpdateListener])
|
private val logger = LoggerFactory.getLogger(classOf[InitializeListener])
|
||||||
|
|
||||||
override def contextInitialized(event: ServletContextEvent): Unit = {
|
override def contextInitialized(event: ServletContextEvent): Unit = {
|
||||||
val dataDir = event.getServletContext.getInitParameter("gitbucket.home")
|
val dataDir = event.getServletContext.getInitParameter("gitbucket.home")
|
||||||
@@ -184,14 +185,14 @@ class AutoUpdateListener extends ServletContextListener {
|
|||||||
}
|
}
|
||||||
// Load plugins
|
// Load plugins
|
||||||
logger.debug("Initialize plugins")
|
logger.debug("Initialize plugins")
|
||||||
PluginRegistry.initialize(conn)
|
PluginRegistry.initialize(event.getServletContext, conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def contextDestroyed(sce: ServletContextEvent): Unit = {
|
def contextDestroyed(event: ServletContextEvent): Unit = {
|
||||||
// Shutdown plugins
|
// Shutdown plugins
|
||||||
PluginRegistry.shutdown()
|
PluginRegistry.shutdown(event.getServletContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
private def getConnection(): Connection =
|
private def getConnection(): Connection =
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
package servlet
|
|
||||||
|
|
||||||
import javax.servlet._
|
|
||||||
import javax.servlet.http.{HttpServletResponse, HttpServletRequest}
|
|
||||||
|
|
||||||
import model.Account
|
|
||||||
import play.twirl.api.Html
|
|
||||||
import plugin.PluginRegistry
|
|
||||||
import service.SystemSettingsService
|
|
||||||
import util.Keys
|
|
||||||
import app.Context
|
|
||||||
import plugin.Results._
|
|
||||||
import plugin.Sessions._
|
|
||||||
|
|
||||||
class PluginActionFilter extends Filter with SystemSettingsService {
|
|
||||||
|
|
||||||
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 =>
|
|
||||||
// Create Context
|
|
||||||
val loginAccount = req.getSession.getAttribute(Keys.Session.LoginAccount).asInstanceOf[Account]
|
|
||||||
implicit val context = Context(loadSystemSettings(), Option(loginAccount), req)
|
|
||||||
sessions.set(Database.getSession(req))
|
|
||||||
try {
|
|
||||||
// Invoke global action
|
|
||||||
action(req, res, context) 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")
|
|
||||||
// TODO title of plugin action
|
|
||||||
res.getWriter.write(html.main("TODO")(x).body)
|
|
||||||
res.getWriter.flush()
|
|
||||||
case Redirect(x) =>
|
|
||||||
res.sendRedirect(x)
|
|
||||||
case Fragment(x) =>
|
|
||||||
res.getWriter.write(x.body)
|
|
||||||
res.getWriter.flush()
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
sessions.remove()
|
|
||||||
}
|
|
||||||
}.getOrElse {
|
|
||||||
chain.doFilter(req, res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -12,10 +12,10 @@
|
|||||||
</listener>
|
</listener>
|
||||||
|
|
||||||
<!-- ===================================================================== -->
|
<!-- ===================================================================== -->
|
||||||
<!-- Automatic migration -->
|
<!-- Automatic migration and plug-in initialization -->
|
||||||
<!-- ===================================================================== -->
|
<!-- ===================================================================== -->
|
||||||
<listener>
|
<listener>
|
||||||
<listener-class>servlet.AutoUpdateListener</listener-class>
|
<listener-class>servlet.InitializeListener</listener-class>
|
||||||
</listener>
|
</listener>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user