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.core.plugins.config.PluginConfigRepository
import de.grimsi.gameyfin.pluginapi.core.GameyfinPlugin import de.grimsi.gameyfin.pluginapi.core.GameyfinPlugin
import io.github.oshai.kotlinlogging.KotlinLogging import io.github.oshai.kotlinlogging.KotlinLogging
import org.pf4j.AbstractPluginManager
import org.pf4j.CompoundPluginDescriptorFinder
import org.pf4j.CompoundPluginLoader import org.pf4j.CompoundPluginLoader
import org.pf4j.CompoundPluginRepository import org.pf4j.CompoundPluginRepository
import org.pf4j.DefaultExtensionFactory
import org.pf4j.DefaultExtensionFinder
import org.pf4j.DefaultPluginFactory
import org.pf4j.DefaultPluginLoader import org.pf4j.DefaultPluginLoader
import org.pf4j.DefaultPluginManager
import org.pf4j.DefaultPluginRepository import org.pf4j.DefaultPluginRepository
import org.pf4j.DefaultVersionManager
import org.pf4j.DevelopmentPluginRepository import org.pf4j.DevelopmentPluginRepository
import org.pf4j.ExtensionFactory
import org.pf4j.ExtensionFinder
import org.pf4j.JarPluginLoader import org.pf4j.JarPluginLoader
import org.pf4j.JarPluginRepository import org.pf4j.JarPluginRepository
import org.pf4j.ManifestPluginDescriptorFinder
import org.pf4j.PluginDescriptorFinder
import org.pf4j.PluginFactory
import org.pf4j.PluginLoader import org.pf4j.PluginLoader
import org.pf4j.PluginRepository import org.pf4j.PluginRepository
import org.pf4j.PluginStatusProvider
import org.pf4j.PluginWrapper import org.pf4j.PluginWrapper
import org.pf4j.PropertiesPluginDescriptorFinder
import org.pf4j.VersionManager
import org.springframework.stereotype.Component
import java.nio.file.Path import java.nio.file.Path
/** /**
* @see https://stackoverflow.com/questions/73654174/my-application-cant-find-the-extension-with-pf4j * @see https://stackoverflow.com/questions/73654174/my-application-cant-find-the-extension-with-pf4j
*/ */
@Component
class GameyfinPluginManager( class GameyfinPluginManager(
path: Path, private val pluginConfigRepository: PluginConfigRepository,
private val pluginConfigRepository: PluginConfigRepository private val pluginStatusProvider: DatabasePluginStatusProvider
) : DefaultPluginManager(path) { ) : AbstractPluginManager() {
private val log = KotlinLogging.logger {} private val log = KotlinLogging.logger {}
@@ -33,6 +48,26 @@ class GameyfinPluginManager(
.add(DefaultPluginRepository(pluginsRoots), this::isNotDevelopment) .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 { override fun createPluginLoader(): PluginLoader {
val compoundPluginLoader = CompoundPluginLoader() val compoundPluginLoader = CompoundPluginLoader()
val developmentPluginLoader = GameyfinPluginLoader(this, javaClass.classLoader) val developmentPluginLoader = GameyfinPluginLoader(this, javaClass.classLoader)
@@ -45,6 +80,14 @@ class GameyfinPluginManager(
.add(defaultPluginLoader, this::isNotDevelopment) .add(defaultPluginLoader, this::isNotDevelopment)
} }
override fun createVersionManager(): VersionManager? {
return DefaultVersionManager()
}
override fun createPluginStatusProvider(): PluginStatusProvider {
return pluginStatusProvider
}
override fun loadPluginFromPath(pluginPath: Path?): PluginWrapper? { override fun loadPluginFromPath(pluginPath: Path?): PluginWrapper? {
val pluginWrapper = super.loadPluginFromPath(pluginPath) val pluginWrapper = super.loadPluginFromPath(pluginPath)
@@ -16,4 +16,8 @@ class PluginManagementEndpoint(
fun stopPlugin(pluginId: String) = pluginManagementService.stopPlugin(pluginId) fun stopPlugin(pluginId: String) = pluginManagementService.stopPlugin(pluginId)
fun restartPlugin(pluginId: String) = pluginManagementService.restartPlugin(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) { fun restartPlugin(pluginId: String) {
pluginManager.restart(pluginId) 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 de.grimsi.gameyfin.core.plugins.config.PluginConfigRepository
import io.github.oshai.kotlinlogging.KotlinLogging import io.github.oshai.kotlinlogging.KotlinLogging
import org.springframework.boot.context.event.ApplicationReadyEvent
import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration import org.springframework.context.annotation.Configuration
import org.springframework.context.event.EventListener
import java.nio.file.Path
@Configuration @Configuration
class PluginManagerConfig( class PluginManagerConfig(
private val pluginConfigRepository: PluginConfigRepository private val pluginConfigRepository: PluginConfigRepository,
private val dbPluginStatusProvider: DatabasePluginStatusProvider
) { ) {
private val log = KotlinLogging.logger {} private val log = KotlinLogging.logger {}
private val pluginPath = System.getProperty("pf4j.pluginsDir", "plugins")
@Bean @Bean
fun pluginManager() = GameyfinPluginManager(Path.of(pluginPath), pluginConfigRepository) fun gameyfinPluginManager(): GameyfinPluginManager {
return GameyfinPluginManager(pluginConfigRepository, dbPluginStatusProvider)
@EventListener(ApplicationReadyEvent::class)
fun loadPlugins() {
pluginManager().loadPlugins()
pluginManager().startPlugins()
log.info { "Loaded plugins: ${pluginManager().plugins.map { it.pluginId }}" }
} }
/*@EventListener(ApplicationReadyEvent::class)
fun loadPlugins() {
gameyfinPluginManager().loadPlugins()
gameyfinPluginManager().startPlugins()
log.info { "Loaded plugins: ${gameyfinPluginManager().plugins.map { it.pluginId }}" }
}*/
} }