Implement PluginManagementService

This commit is contained in:
grimsi
2024-12-03 16:36:39 +01:00
parent b30be5722a
commit 584cc765cb
7 changed files with 126 additions and 16 deletions
@@ -0,0 +1,32 @@
package de.grimsi.gameyfin.core.plugins.management
import org.pf4j.PluginStatusProvider
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Component
@Component
class DatabasePluginStatusProvider(
private val pluginManagementRepository: PluginManagementRepository
) : PluginStatusProvider {
override fun isPluginDisabled(pluginId: String): Boolean {
val pluginManagement = pluginManagementRepository.findByIdOrNull(pluginId)
return pluginManagement?.enabled != true
}
override fun disablePlugin(pluginId: String) {
val pluginManagement = pluginManagementRepository.findByIdOrNull(pluginId)
if (pluginManagement != null) {
pluginManagement.enabled = true
pluginManagementRepository.save(pluginManagement)
}
}
override fun enablePlugin(pluginId: String) {
val pluginManagement = pluginManagementRepository.findByIdOrNull(pluginId)
if (pluginManagement != null) {
pluginManagement.enabled = false
pluginManagementRepository.save(pluginManagement)
}
}
}
@@ -3,26 +3,41 @@ package de.grimsi.gameyfin.core.plugins.management
import de.grimsi.gameyfin.core.plugins.config.PluginConfigRepository
import de.grimsi.gameyfin.pluginapi.core.GameyfinPlugin
import io.github.oshai.kotlinlogging.KotlinLogging
import org.pf4j.AbstractPluginManager
import org.pf4j.CompoundPluginDescriptorFinder
import org.pf4j.CompoundPluginLoader
import org.pf4j.CompoundPluginRepository
import org.pf4j.DefaultExtensionFactory
import org.pf4j.DefaultExtensionFinder
import org.pf4j.DefaultPluginFactory
import org.pf4j.DefaultPluginLoader
import org.pf4j.DefaultPluginManager
import org.pf4j.DefaultPluginRepository
import org.pf4j.DefaultVersionManager
import org.pf4j.DevelopmentPluginRepository
import org.pf4j.ExtensionFactory
import org.pf4j.ExtensionFinder
import org.pf4j.JarPluginLoader
import org.pf4j.JarPluginRepository
import org.pf4j.ManifestPluginDescriptorFinder
import org.pf4j.PluginDescriptorFinder
import org.pf4j.PluginFactory
import org.pf4j.PluginLoader
import org.pf4j.PluginRepository
import org.pf4j.PluginStatusProvider
import org.pf4j.PluginWrapper
import org.pf4j.PropertiesPluginDescriptorFinder
import org.pf4j.VersionManager
import org.springframework.stereotype.Component
import java.nio.file.Path
/**
* @see https://stackoverflow.com/questions/73654174/my-application-cant-find-the-extension-with-pf4j
*/
@Component
class GameyfinPluginManager(
path: Path,
private val pluginConfigRepository: PluginConfigRepository
) : DefaultPluginManager(path) {
private val pluginConfigRepository: PluginConfigRepository,
private val pluginStatusProvider: DatabasePluginStatusProvider
) : AbstractPluginManager() {
private val log = KotlinLogging.logger {}
@@ -33,6 +48,26 @@ class GameyfinPluginManager(
.add(DefaultPluginRepository(pluginsRoots), this::isNotDevelopment)
}
override fun createPluginFactory(): PluginFactory {
return DefaultPluginFactory()
}
override fun createExtensionFactory(): ExtensionFactory {
return DefaultExtensionFactory()
}
override fun createPluginDescriptorFinder(): PluginDescriptorFinder {
return CompoundPluginDescriptorFinder()
.add(PropertiesPluginDescriptorFinder())
.add(ManifestPluginDescriptorFinder())
}
override fun createExtensionFinder(): ExtensionFinder {
val extensionFinder = DefaultExtensionFinder(this)
addPluginStateListener(extensionFinder)
return extensionFinder
}
override fun createPluginLoader(): PluginLoader {
val compoundPluginLoader = CompoundPluginLoader()
val developmentPluginLoader = GameyfinPluginLoader(this, javaClass.classLoader)
@@ -45,6 +80,14 @@ class GameyfinPluginManager(
.add(defaultPluginLoader, this::isNotDevelopment)
}
override fun createVersionManager(): VersionManager? {
return DefaultVersionManager()
}
override fun createPluginStatusProvider(): PluginStatusProvider {
return pluginStatusProvider
}
override fun loadPluginFromPath(pluginPath: Path?): PluginWrapper? {
val pluginWrapper = super.loadPluginFromPath(pluginPath)
@@ -16,4 +16,8 @@ class PluginManagementEndpoint(
fun stopPlugin(pluginId: String) = pluginManagementService.stopPlugin(pluginId)
fun restartPlugin(pluginId: String) = pluginManagementService.restartPlugin(pluginId)
fun enablePlugin(pluginId: String) = pluginManagementService.enablePlugin(pluginId)
fun disablePlugin(pluginId: String) = pluginManagementService.disablePlugin(pluginId)
}
@@ -0,0 +1,19 @@
package de.grimsi.gameyfin.core.plugins.management
import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.Id
import jakarta.persistence.Table
import jakarta.validation.constraints.NotNull
@Entity
@Table(name = "plugin_management")
data class PluginManagementEntry(
@Id
@Column(name = "plugin_id")
val pluginId: String,
@NotNull
@Column(name = "enabled")
var enabled: Boolean = true
)
@@ -0,0 +1,5 @@
package de.grimsi.gameyfin.core.plugins.management
import org.springframework.data.jpa.repository.JpaRepository
interface PluginManagementRepository : JpaRepository<PluginManagementEntry, String>
@@ -29,4 +29,12 @@ class PluginManagementService(
fun restartPlugin(pluginId: String) {
pluginManager.restart(pluginId)
}
fun enablePlugin(pluginId: String) {
pluginManager.enablePlugin(pluginId)
}
fun disablePlugin(pluginId: String) {
pluginManager.disablePlugin(pluginId)
}
}
@@ -2,26 +2,25 @@ package de.grimsi.gameyfin.core.plugins.management
import de.grimsi.gameyfin.core.plugins.config.PluginConfigRepository
import io.github.oshai.kotlinlogging.KotlinLogging
import org.springframework.boot.context.event.ApplicationReadyEvent
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.event.EventListener
import java.nio.file.Path
@Configuration
class PluginManagerConfig(
private val pluginConfigRepository: PluginConfigRepository
private val pluginConfigRepository: PluginConfigRepository,
private val dbPluginStatusProvider: DatabasePluginStatusProvider
) {
private val log = KotlinLogging.logger {}
private val pluginPath = System.getProperty("pf4j.pluginsDir", "plugins")
@Bean
fun pluginManager() = GameyfinPluginManager(Path.of(pluginPath), pluginConfigRepository)
@EventListener(ApplicationReadyEvent::class)
fun loadPlugins() {
pluginManager().loadPlugins()
pluginManager().startPlugins()
log.info { "Loaded plugins: ${pluginManager().plugins.map { it.pluginId }}" }
fun gameyfinPluginManager(): GameyfinPluginManager {
return GameyfinPluginManager(pluginConfigRepository, dbPluginStatusProvider)
}
/*@EventListener(ApplicationReadyEvent::class)
fun loadPlugins() {
gameyfinPluginManager().loadPlugins()
gameyfinPluginManager().startPlugins()
log.info { "Loaded plugins: ${gameyfinPluginManager().plugins.map { it.pluginId }}" }
}*/
}