Add migration system for plugins

This commit is contained in:
Naoki Takezoe
2015-02-08 22:31:09 +09:00
parent 7e77398645
commit 6888d959e1
4 changed files with 93 additions and 13 deletions

View File

@@ -1,11 +1,13 @@
package plugin
import util.Version
trait Plugin {
val pluginId: String
val pluginName: String
val description: String
val version: String
val versions: List[Version]
def initialize(registry: PluginRegistry): Unit

View File

@@ -8,6 +8,7 @@ import org.slf4j.LoggerFactory
import service.RepositoryService.RepositoryInfo
import util.Directory._
import util.JDBCUtil._
import util.{Version, Versions}
import scala.collection.mutable.ListBuffer
@@ -88,24 +89,36 @@ object PluginRegistry {
val classLoader = new URLClassLoader(Array(pluginJar.toURI.toURL), Thread.currentThread.getContextClassLoader)
try {
val plugin = classLoader.loadClass("Plugin").newInstance().asInstanceOf[Plugin]
// Migration
val headVersion = plugin.versions.head
val currentVersion = conn.find("SELECT * FROM PLUGIN WHERE PLUGIN_ID = ?", plugin.pluginId)(_.getString("VERSION")) match {
case Some(x) => {
val dim = x.split("\\.")
Version(dim(0).toInt, dim(1).toInt)
}
case None => Version(0, 0)
}
Versions.update(conn, headVersion, currentVersion, plugin.versions, new URLClassLoader(Array(pluginJar.toURI.toURL))){ conn =>
currentVersion.versionString match {
case "0.0" =>
conn.update("INSERT INTO PLUGIN (PLUGIN_ID, VERSION) VALUES (?, ?)", plugin.pluginId, headVersion.versionString)
case _ =>
conn.update("UPDATE PLUGIN SET VERSION = ? WHERE PLUGIN_ID = ?", headVersion.versionString, plugin.pluginId)
}
}
// Initialize
plugin.initialize(instance)
instance.addPlugin(PluginInfo(
pluginId = plugin.pluginId,
pluginName = plugin.pluginName,
version = plugin.version,
version = plugin.versions.head.versionString,
description = plugin.description,
pluginClass = plugin
))
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)

View File

@@ -13,8 +13,6 @@ import org.eclipse.jgit.api.Git
import util.Directory
import plugin._
import scala.slick.jdbc.meta.MBestRowIdentifierColumn.Scope.Session
object AutoUpdate {
/**

View File

@@ -0,0 +1,67 @@
package util
import java.sql.Connection
import org.apache.commons.io.IOUtils
import org.slf4j.LoggerFactory
import util.ControlUtil._
case class Version(majorVersion: Int, minorVersion: Int) {
private val logger = LoggerFactory.getLogger(classOf[Version])
/**
* Execute update/MAJOR_MINOR.sql to update schema to this version.
* If corresponding SQL file does not exist, this method do nothing.
*/
def update(conn: Connection, cl: ClassLoader): Unit = {
val sqlPath = s"update/${majorVersion}_${minorVersion}.sql"
using(cl.getResourceAsStream(sqlPath)){ in =>
if(in != null){
val sql = IOUtils.toString(in, "UTF-8")
using(conn.createStatement()){ stmt =>
logger.debug(sqlPath + "=" + sql)
stmt.executeUpdate(sql)
}
}
}
}
/**
* MAJOR.MINOR
*/
val versionString = s"${majorVersion}.${minorVersion}"
}
object Versions {
private val logger = LoggerFactory.getLogger(Versions.getClass)
def update(conn: Connection, headVersion: Version, currentVersion: Version, versions: List[Version], cl: ClassLoader)
(save: Connection => Unit): Unit = {
logger.debug("Start schema update")
try {
if(currentVersion == headVersion){
logger.debug("No update")
} else if(currentVersion.versionString != "0.0" && !versions.contains(currentVersion)){
logger.warn(s"Skip migration because ${currentVersion.versionString} is illegal version.")
} else {
versions.takeWhile(_ != currentVersion).reverse.foreach(_.update(conn, cl))
save(conn)
logger.debug(s"Updated from ${currentVersion.versionString} to ${headVersion.versionString}")
}
} catch {
case ex: Throwable => {
logger.error("Failed to schema update", ex)
ex.printStackTrace()
conn.rollback()
}
}
logger.debug("End schema update")
}
}