diff --git a/src/main/scala/app/SystemSettingsController.scala b/src/main/scala/app/SystemSettingsController.scala index a879670..9cfed5f 100644 --- a/src/main/scala/app/SystemSettingsController.scala +++ b/src/main/scala/app/SystemSettingsController.scala @@ -10,7 +10,7 @@ import org.scalatra.Ok import org.apache.commons.io.FileUtils import java.io.FileInputStream -import plugin.PluginSystem +import plugin.{Plugin, PluginSystem} class SystemSettingsController extends SystemSettingsControllerBase with AccountService with AdminAuthenticator @@ -83,36 +83,32 @@ }) get("/admin/plugins")(adminOnly { - admin.plugins.html.installed(plugin.PluginSystem.plugins) + val installedPlugins = plugin.PluginSystem.plugins + val updatablePlugins = getAvailablePlugins(installedPlugins).filter(_.status == "updatable") + admin.plugins.html.installed(installedPlugins, updatablePlugins) + }) + + post("/admin/plugins/_update", pluginForm)(adminOnly { form => + deletePlugins(form.pluginIds) + installPlugins(form.pluginIds) + redirect("/admin/plugins") }) post("/admin/plugins/_delete", pluginForm)(adminOnly { form => - form.pluginIds.foreach { pluginId => - plugin.PluginSystem.uninstall(pluginId) - val dir = new java.io.File(PluginHome, pluginId) - if(dir.exists && dir.isDirectory){ - FileUtils.deleteQuietly(dir) - PluginSystem.uninstall(pluginId) - } - } + deletePlugins(form.pluginIds) redirect("/admin/plugins") }) get("/admin/plugins/available")(adminOnly { // TODO Do periodical and asynchronous...? PluginSystem.updateAllRepositories() - admin.plugins.html.available(getAvailablePlugins()) + val installedPlugins = plugin.PluginSystem.plugins + val availablePlugins = getAvailablePlugins(installedPlugins).filter(_.status == "available") + admin.plugins.html.available(availablePlugins) }) post("/admin/plugins/_install", pluginForm)(adminOnly { form => - val dir = getPluginCacheDir() - getAvailablePlugins().filter(x => form.pluginIds.contains(x.id)).foreach { plugin => - val pluginDir = new java.io.File(PluginHome, plugin.id) - if(!pluginDir.exists){ - FileUtils.copyDirectory(new java.io.File(dir, plugin.repository + "/" + plugin.id), pluginDir) - } - PluginSystem.installPlugin(plugin.id) - } + installPlugins(form.pluginIds) redirect("/admin/plugins") }) @@ -126,9 +122,31 @@ Ok(result) }) - // TODO Move to PluginSystem or Service? - private def getAvailablePlugins(): List[SystemSettingsControllerBase.AvailablePlugin] = { + // TODO Move these methods to PluginSystem or Service? + private def deletePlugins(pluginIds: List[String]): Unit = { + pluginIds.foreach { pluginId => + plugin.PluginSystem.uninstall(pluginId) + val dir = new java.io.File(PluginHome, pluginId) + if(dir.exists && dir.isDirectory){ + FileUtils.deleteQuietly(dir) + PluginSystem.uninstall(pluginId) + } + } + } + + private def installPlugins(pluginIds: List[String]): Unit = { + val dir = getPluginCacheDir() val installedPlugins = plugin.PluginSystem.plugins + getAvailablePlugins(installedPlugins).filter(x => pluginIds.contains(x.id)).foreach { plugin => + val pluginDir = new java.io.File(PluginHome, plugin.id) + if(!pluginDir.exists){ + FileUtils.copyDirectory(new java.io.File(dir, plugin.repository + "/" + plugin.id), pluginDir) + } + PluginSystem.installPlugin(plugin.id) + } + } + + private def getAvailablePlugins(installedPlugins: List[Plugin]): List[SystemSettingsControllerBase.AvailablePlugin] = { val repositoryRoot = getPluginCacheDir() if(repositoryRoot.exists && repositoryRoot.isDirectory){ @@ -144,16 +162,20 @@ } } SystemSettingsControllerBase.AvailablePlugin( - repo.id, - properties.getProperty("id"), - properties.getProperty("version"), - properties.getProperty("author"), - properties.getProperty("url"), - properties.getProperty("description"), - if(installedPlugins.exists(_.id == properties.getProperty("id"))) "installed" else "available") + repository = repo.id, + id = properties.getProperty("id"), + version = properties.getProperty("version"), + author = properties.getProperty("author"), + url = properties.getProperty("url"), + description = properties.getProperty("description"), + status = installedPlugins.find(_.id == properties.getProperty("id")) match { + case Some(x) if(PluginSystem.isUpdatable(x.version, properties.getProperty("version")))=> "updatable" + case Some(x) => "installed" + case None => "available" + }) } } else Nil - }.filter(x => !installedPlugins.exists(_.id == x.id)) + } } else Nil } } diff --git a/src/main/scala/plugin/PluginSystem.scala b/src/main/scala/plugin/PluginSystem.scala index df00943..1f095e5 100644 --- a/src/main/scala/plugin/PluginSystem.scala +++ b/src/main/scala/plugin/PluginSystem.scala @@ -106,6 +106,28 @@ } } + /** + * Checks whether the plugin is updatable. + */ + def isUpdatable(oldVersion: String, newVersion: String): Boolean = { + if(oldVersion == newVersion){ + false + } else { + val dim1 = oldVersion.split("\\.").map(_.toInt) + val dim2 = newVersion.split("\\.").map(_.toInt) + dim1.zip(dim2).foreach { case (a, b) => + if(a < b){ + return true + } else if(a > b){ + return false + } + } + return false + } + } + + + // 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") // { context => context.loginAccount.isDefined } diff --git a/src/main/twirl/admin/plugins/available.scala.html b/src/main/twirl/admin/plugins/available.scala.html index ee5eeff..fcf37a0 100644 --- a/src/main/twirl/admin/plugins/available.scala.html +++ b/src/main/twirl/admin/plugins/available.scala.html @@ -24,7 +24,7 @@ } - + } } diff --git a/src/main/twirl/admin/plugins/installed.scala.html b/src/main/twirl/admin/plugins/installed.scala.html index 2c86c0d..f85c149 100644 --- a/src/main/twirl/admin/plugins/installed.scala.html +++ b/src/main/twirl/admin/plugins/installed.scala.html @@ -1,10 +1,11 @@ -@(plugins: List[plugin.Plugin])(implicit context: app.Context) +@(plugins: List[plugin.Plugin], + updatablePlugins: List[app.SystemSettingsControllerBase.AvailablePlugin])(implicit context: app.Context) @import context._ @import view.helpers._ @html.main("Plugins"){ @admin.html.menu("plugins"){ @tab("installed") -
+ @@ -18,18 +19,27 @@ @plugin.id - + }
ID@plugin.version + @plugin.version + @updatablePlugins.find(_.id == plugin.id).map { x => + (@x.version is available) + } + @plugin.author @plugin.description
- + +
} }