package plugin import ( "context" "encoding/json" "errors" "fmt" "io/fs" "os" "path/filepath" "plugin" "runtime" "sync" ) // Plugin 插件接口 type Plugin interface { // Name 插件名称 Name() string // Version 插件版本 Version() string // Description 插件描述 Description() string // Author 插件作者 Author() string // Type 插件类型 Type() PluginType // Init 初始化插件 Init(ctx context.Context, config map[string]interface{}) error // Start 启动插件 Start(ctx context.Context) error // Stop 停止插件 Stop(ctx context.Context) error // IsEnabled 插件是否启用 IsEnabled() bool // SetEnabled 设置插件启用状态 SetEnabled(enabled bool) } // PluginInfo 插件信息 type PluginInfo struct { Name string `json:"name"` Version string `json:"version"` Description string `json:"description"` Author string `json:"author"` Type PluginType `json:"type"` Enabled bool `json:"enabled"` Config map[string]interface{} `json:"config,omitempty"` } // PluginManager 插件管理器 type PluginManager struct { pluginsDir string plugins map[string]Plugin pluginsByType map[PluginType]map[string]Plugin configs map[string]map[string]interface{} mu sync.RWMutex dynamicLoadingSupported bool // 是否支持动态加载插件 } // NewPluginManager 创建插件管理器 func NewPluginManager(pluginsDir string) *PluginManager { // 检查当前系统是否支持动态加载插件 dynamicLoadingSupported := runtime.GOOS == "linux" || runtime.GOOS == "darwin" return &PluginManager{ pluginsDir: pluginsDir, plugins: make(map[string]Plugin), pluginsByType: make(map[PluginType]map[string]Plugin), configs: make(map[string]map[string]interface{}), dynamicLoadingSupported: dynamicLoadingSupported, } } // IsDynamicLoadingSupported 检查是否支持动态加载插件 func (pm *PluginManager) IsDynamicLoadingSupported() bool { return pm.dynamicLoadingSupported } // LoadPlugins 加载插件 func (pm *PluginManager) LoadPlugins() error { // 确保插件目录存在 if err := os.MkdirAll(pm.pluginsDir, 0o755); err != nil { return fmt.Errorf("创建插件目录失败: %v", err) } // 加载插件配置 if err := pm.loadPluginConfigs(); err != nil { return fmt.Errorf("加载插件配置失败: %v", err) } // 如果不支持动态加载,则返回 if !pm.dynamicLoadingSupported { fmt.Printf("警告: 当前系统(%s)不支持动态加载插件,跳过加载\n", runtime.GOOS) return nil } // 遍历插件目录 err := filepath.Walk(pm.pluginsDir, func(path string, info fs.FileInfo, err error) error { if err != nil { return err } // 跳过目录和非.so文件 if info.IsDir() || filepath.Ext(path) != ".so" { return nil } // 加载插件 if err := pm.loadPlugin(path); err != nil { fmt.Printf("加载插件 %s 失败: %v\n", path, err) } return nil }) return err } // loadPluginConfigs 加载插件配置 func (pm *PluginManager) loadPluginConfigs() error { configPath := filepath.Join(pm.pluginsDir, "plugins.json") // 如果配置文件不存在,创建一个空的 if _, err := os.Stat(configPath); os.IsNotExist(err) { file, err := os.Create(configPath) if err != nil { return fmt.Errorf("创建插件配置文件失败: %v", err) } file.Write([]byte("{}")) file.Close() return nil } // 读取配置文件 data, err := os.ReadFile(configPath) if err != nil { return fmt.Errorf("读取插件配置文件失败: %v", err) } // 解析配置 var configs map[string]map[string]interface{} if err := json.Unmarshal(data, &configs); err != nil { return fmt.Errorf("解析插件配置文件失败: %v", err) } pm.configs = configs return nil } // savePluginConfigs 保存插件配置 func (pm *PluginManager) savePluginConfigs() error { configPath := filepath.Join(pm.pluginsDir, "plugins.json") // 创建配置数据 configs := make(map[string]map[string]interface{}) pm.mu.RLock() for name, plugin := range pm.plugins { config := pm.configs[name] if config == nil { config = make(map[string]interface{}) } config["enabled"] = plugin.IsEnabled() config["type"] = string(plugin.Type()) // 保存插件类型 configs[name] = config } pm.mu.RUnlock() // 序列化配置 data, err := json.MarshalIndent(configs, "", " ") if err != nil { return fmt.Errorf("序列化插件配置失败: %v", err) } // 写入文件 if err := os.WriteFile(configPath, data, 0o644); err != nil { return fmt.Errorf("写入插件配置文件失败: %v", err) } return nil } // loadPlugin 加载单个插件 func (pm *PluginManager) loadPlugin(path string) error { // 打开插件文件 p, err := plugin.Open(path) if err != nil { return fmt.Errorf("打开插件失败: %v", err) } // 查找Plugin变量 symPlugin, err := p.Lookup("Plugin") if err != nil { return fmt.Errorf("查找Plugin变量失败: %v", err) } // 类型断言 plugin, ok := symPlugin.(Plugin) if !ok { return errors.New("插件类型错误") } // 检查插件名称是否已存在 pm.mu.Lock() defer pm.mu.Unlock() if _, exists := pm.plugins[plugin.Name()]; exists { return fmt.Errorf("插件 %s 已存在", plugin.Name()) } // 设置插件启用状态 if config, exists := pm.configs[plugin.Name()]; exists { if enabled, ok := config["enabled"].(bool); ok { plugin.SetEnabled(enabled) } else { plugin.SetEnabled(true) // 默认启用 } } else { plugin.SetEnabled(true) // 默认启用 } // 注册插件 pm.registerPlugin(plugin) return nil } // registerPlugin 注册插件到插件管理器 func (pm *PluginManager) registerPlugin(plugin Plugin) { pluginType := plugin.Type() // 将插件添加到按名称索引的映射 pm.plugins[plugin.Name()] = plugin // 将插件添加到按类型索引的映射 if pm.pluginsByType[pluginType] == nil { pm.pluginsByType[pluginType] = make(map[string]Plugin) } pm.pluginsByType[pluginType][plugin.Name()] = plugin } // RegisterPlugin 注册内置插件 // 用于在不支持动态加载的平台上注册插件 func (pm *PluginManager) RegisterPlugin(plugin Plugin) error { pm.mu.Lock() defer pm.mu.Unlock() if _, exists := pm.plugins[plugin.Name()]; exists { return fmt.Errorf("插件 %s 已存在", plugin.Name()) } // 设置插件启用状态 if config, exists := pm.configs[plugin.Name()]; exists { if enabled, ok := config["enabled"].(bool); ok { plugin.SetEnabled(enabled) } else { plugin.SetEnabled(true) // 默认启用 } } else { plugin.SetEnabled(true) // 默认启用 } // 注册插件 pm.registerPlugin(plugin) return nil } // GetPlugin 获取插件 func (pm *PluginManager) GetPlugin(name string) (Plugin, bool) { pm.mu.RLock() defer pm.mu.RUnlock() plugin, exists := pm.plugins[name] return plugin, exists } // GetPluginsByType 按类型获取插件 func (pm *PluginManager) GetPluginsByType(pluginType PluginType) []Plugin { pm.mu.RLock() defer pm.mu.RUnlock() plugins := make([]Plugin, 0) if typePlugins, exists := pm.pluginsByType[pluginType]; exists { for _, plugin := range typePlugins { if plugin.IsEnabled() { plugins = append(plugins, plugin) } } } return plugins } // GetAllPluginsByType 获取所有指定类型的插件,无论是否启用 func (pm *PluginManager) GetAllPluginsByType(pluginType PluginType) []Plugin { pm.mu.RLock() defer pm.mu.RUnlock() plugins := make([]Plugin, 0) if typePlugins, exists := pm.pluginsByType[pluginType]; exists { for _, plugin := range typePlugins { plugins = append(plugins, plugin) } } return plugins } // GetAllPlugins 获取所有插件 func (pm *PluginManager) GetAllPlugins() []Plugin { pm.mu.RLock() defer pm.mu.RUnlock() plugins := make([]Plugin, 0, len(pm.plugins)) for _, plugin := range pm.plugins { plugins = append(plugins, plugin) } return plugins } // GetPluginInfos 获取所有插件信息 func (pm *PluginManager) GetPluginInfos() []PluginInfo { pm.mu.RLock() defer pm.mu.RUnlock() infos := make([]PluginInfo, 0, len(pm.plugins)) for name, plugin := range pm.plugins { info := PluginInfo{ Name: plugin.Name(), Version: plugin.Version(), Description: plugin.Description(), Author: plugin.Author(), Type: plugin.Type(), Enabled: plugin.IsEnabled(), Config: pm.configs[name], } infos = append(infos, info) } return infos } // GetPluginInfosByType 按类型获取插件信息 func (pm *PluginManager) GetPluginInfosByType(pluginType PluginType) []PluginInfo { pm.mu.RLock() defer pm.mu.RUnlock() infos := make([]PluginInfo, 0) if typePlugins, exists := pm.pluginsByType[pluginType]; exists { for name, plugin := range typePlugins { info := PluginInfo{ Name: plugin.Name(), Version: plugin.Version(), Description: plugin.Description(), Author: plugin.Author(), Type: plugin.Type(), Enabled: plugin.IsEnabled(), Config: pm.configs[name], } infos = append(infos, info) } } return infos } // EnablePlugin 启用插件 func (pm *PluginManager) EnablePlugin(name string) error { pm.mu.Lock() defer pm.mu.Unlock() plugin, exists := pm.plugins[name] if !exists { return fmt.Errorf("插件 %s 不存在", name) } plugin.SetEnabled(true) // 更新配置 if pm.configs[name] == nil { pm.configs[name] = make(map[string]interface{}) } pm.configs[name]["enabled"] = true // 保存配置 return pm.savePluginConfigs() } // DisablePlugin 禁用插件 func (pm *PluginManager) DisablePlugin(name string) error { pm.mu.Lock() defer pm.mu.Unlock() plugin, exists := pm.plugins[name] if !exists { return fmt.Errorf("插件 %s 不存在", name) } plugin.SetEnabled(false) // 更新配置 if pm.configs[name] == nil { pm.configs[name] = make(map[string]interface{}) } pm.configs[name]["enabled"] = false // 保存配置 return pm.savePluginConfigs() } // InitPlugins 初始化所有插件 func (pm *PluginManager) InitPlugins(ctx context.Context) error { pm.mu.RLock() defer pm.mu.RUnlock() for name, plugin := range pm.plugins { if !plugin.IsEnabled() { continue } config := pm.configs[name] if err := plugin.Init(ctx, config); err != nil { return fmt.Errorf("初始化插件 %s 失败: %v", name, err) } } return nil } // InitPluginsByType 初始化指定类型的所有插件 func (pm *PluginManager) InitPluginsByType(ctx context.Context, pluginType PluginType) error { pm.mu.RLock() defer pm.mu.RUnlock() if typePlugins, exists := pm.pluginsByType[pluginType]; exists { for name, plugin := range typePlugins { if !plugin.IsEnabled() { continue } config := pm.configs[name] if err := plugin.Init(ctx, config); err != nil { return fmt.Errorf("初始化插件 %s 失败: %v", name, err) } } } return nil } // StartPlugins 启动所有插件 func (pm *PluginManager) StartPlugins(ctx context.Context) error { pm.mu.RLock() defer pm.mu.RUnlock() for name, plugin := range pm.plugins { if !plugin.IsEnabled() { continue } if err := plugin.Start(ctx); err != nil { return fmt.Errorf("启动插件 %s 失败: %v", name, err) } } return nil } // StartPluginsByType 启动指定类型的所有插件 func (pm *PluginManager) StartPluginsByType(ctx context.Context, pluginType PluginType) error { pm.mu.RLock() defer pm.mu.RUnlock() if typePlugins, exists := pm.pluginsByType[pluginType]; exists { for name, plugin := range typePlugins { if !plugin.IsEnabled() { continue } if err := plugin.Start(ctx); err != nil { return fmt.Errorf("启动插件 %s 失败: %v", name, err) } } } return nil } // StopPlugins 停止所有插件 func (pm *PluginManager) StopPlugins(ctx context.Context) error { pm.mu.RLock() defer pm.mu.RUnlock() for name, plugin := range pm.plugins { if !plugin.IsEnabled() { continue } if err := plugin.Stop(ctx); err != nil { return fmt.Errorf("停止插件 %s 失败: %v", name, err) } } return nil } // StopPluginsByType 停止指定类型的所有插件 func (pm *PluginManager) StopPluginsByType(ctx context.Context, pluginType PluginType) error { pm.mu.RLock() defer pm.mu.RUnlock() if typePlugins, exists := pm.pluginsByType[pluginType]; exists { for name, plugin := range typePlugins { if !plugin.IsEnabled() { continue } if err := plugin.Stop(ctx); err != nil { return fmt.Errorf("停止插件 %s 失败: %v", name, err) } } } return nil } // SetPluginConfig 设置插件配置 func (pm *PluginManager) SetPluginConfig(name string, config map[string]interface{}) error { pm.mu.Lock() defer pm.mu.Unlock() if _, exists := pm.plugins[name]; !exists { return fmt.Errorf("插件 %s 不存在", name) } pm.configs[name] = config return pm.savePluginConfigs() } // GetPluginConfig 获取插件配置 func (pm *PluginManager) GetPluginConfig(name string) (map[string]interface{}, error) { pm.mu.RLock() defer pm.mu.RUnlock() if _, exists := pm.plugins[name]; !exists { return nil, fmt.Errorf("插件 %s 不存在", name) } config := pm.configs[name] if config == nil { config = make(map[string]interface{}) } return config, nil }