- 在插件管理器中引入 DynamicPlugin 结构体,支持动态加载和管理插件,提升插件的灵活性和可扩展性。 - 更新插件接口,添加插件名称、版本、描述、作者、类型和启用状态的获取和设置方法,增强插件信息的管理能力。 - 修改现有插件实现,确保兼容新的动态插件结构,提升插件的统一性和可维护性。 - 更新示例程序,展示如何使用新的动态插件功能,提升用户体验。 此更新提升了插件系统的灵活性和可扩展性,便于开发者更好地管理和使用插件功能。
1871 lines
49 KiB
Go
1871 lines
49 KiB
Go
package plugin
|
||
|
||
import (
|
||
"context"
|
||
"encoding/json"
|
||
"fmt"
|
||
"io/fs"
|
||
"os"
|
||
"path/filepath"
|
||
"plugin"
|
||
"reflect"
|
||
"runtime"
|
||
"strconv"
|
||
"strings"
|
||
"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)
|
||
// Execute 执行插件功能
|
||
// action: 要执行的操作名称
|
||
// params: 操作所需的参数
|
||
// 返回操作结果和可能的错误
|
||
Execute(ctx context.Context, action string, params map[string]interface{}) (interface{}, error)
|
||
// GetOperationInfo 获取操作的参数信息
|
||
GetOperationInfo(operation string) (map[string]interface{}, error)
|
||
// GetAllOperations 获取所有操作及其参数信息
|
||
GetAllOperations() map[string]map[string]interface{}
|
||
}
|
||
|
||
// PluginHelper 插件辅助器
|
||
// 用于自动发现和注册插件方法,简化Execute方法的实现
|
||
type PluginHelper struct {
|
||
instance interface{} // 插件实例
|
||
methods map[string]reflect.Method // 注册的方法
|
||
methodParams map[string][]reflect.Type // 方法的参数类型
|
||
methodRetValues map[string][]reflect.Type // 方法的返回值类型
|
||
}
|
||
|
||
// NewPluginHelper 创建一个新的插件辅助器
|
||
func NewPluginHelper(instance interface{}) *PluginHelper {
|
||
helper := &PluginHelper{
|
||
instance: instance,
|
||
methods: make(map[string]reflect.Method),
|
||
methodParams: make(map[string][]reflect.Type),
|
||
methodRetValues: make(map[string][]reflect.Type),
|
||
}
|
||
helper.discoverMethods()
|
||
return helper
|
||
}
|
||
|
||
// discoverMethods 发现插件的所有可用方法
|
||
func (h *PluginHelper) discoverMethods() {
|
||
instanceType := reflect.TypeOf(h.instance)
|
||
|
||
// 遍历实例的所有方法
|
||
for i := 0; i < instanceType.NumMethod(); i++ {
|
||
method := instanceType.Method(i)
|
||
|
||
// 跳过特定的内部方法和接口方法
|
||
if shouldSkipMethod(method.Name) {
|
||
continue
|
||
}
|
||
|
||
// 获取方法的参数和返回值类型
|
||
var paramTypes []reflect.Type
|
||
var returnTypes []reflect.Type
|
||
|
||
// 跳过接收者参数 (第一个参数)
|
||
for j := 1; j < method.Type.NumIn(); j++ {
|
||
paramTypes = append(paramTypes, method.Type.In(j))
|
||
}
|
||
|
||
for j := 0; j < method.Type.NumOut(); j++ {
|
||
returnTypes = append(returnTypes, method.Type.Out(j))
|
||
}
|
||
|
||
// 注册方法
|
||
actionName := strings.ToLower(method.Name)
|
||
h.methods[actionName] = method
|
||
h.methodParams[actionName] = paramTypes
|
||
h.methodRetValues[actionName] = returnTypes
|
||
}
|
||
}
|
||
|
||
// shouldSkipMethod 检查是否应该跳过某些方法
|
||
func shouldSkipMethod(name string) bool {
|
||
// 跳过Plugin接口的方法和特定的内部方法
|
||
skipMethods := map[string]bool{
|
||
"Name": true,
|
||
"Version": true,
|
||
"Description": true,
|
||
"Author": true,
|
||
"Type": true,
|
||
"Init": true,
|
||
"Start": true,
|
||
"Stop": true,
|
||
"IsEnabled": true,
|
||
"SetEnabled": true,
|
||
"Execute": true,
|
||
}
|
||
|
||
return skipMethods[name]
|
||
}
|
||
|
||
// GetAvailableActions 获取所有可用的动作
|
||
func (h *PluginHelper) GetAvailableActions() []string {
|
||
actions := make([]string, 0, len(h.methods))
|
||
for action := range h.methods {
|
||
actions = append(actions, action)
|
||
}
|
||
return actions
|
||
}
|
||
|
||
// ValidateParams 验证传入的参数是否符合操作的参数定义
|
||
func ValidateParams(paramsDef map[string]interface{}, params map[string]interface{}) error {
|
||
// 检查参数定义是否存在
|
||
if paramsDef == nil {
|
||
return nil // 没有参数定义,不需要验证
|
||
}
|
||
|
||
// 获取参数定义中的每个参数
|
||
paramsInfo, ok := paramsDef["parameters"].(map[string]interface{})
|
||
if !ok {
|
||
return nil // 参数定义格式不正确,跳过验证
|
||
}
|
||
|
||
// 遍历每个参数定义进行验证
|
||
errors := make([]string, 0)
|
||
|
||
for paramName, paramInfo := range paramsInfo {
|
||
info, ok := paramInfo.(map[string]interface{})
|
||
if !ok {
|
||
continue // 参数信息格式不正确,跳过
|
||
}
|
||
|
||
// 检查是否为必需参数
|
||
required, ok := info["required"].(bool)
|
||
if ok && required {
|
||
// 对于结构体参数,要检查至少有一个字段被提供
|
||
if info["type"] == "struct" {
|
||
// 结构体参数的验证
|
||
if fields, ok := info["fields"].(map[string]interface{}); ok {
|
||
// 检查必填的结构体字段
|
||
for fieldName, fieldInfo := range fields {
|
||
if fieldInfoMap, ok := fieldInfo.(map[string]interface{}); ok {
|
||
fieldRequired, ok := fieldInfoMap["required"].(bool)
|
||
if ok && fieldRequired {
|
||
if _, exists := params[fieldName]; !exists {
|
||
errors = append(errors, fmt.Sprintf("缺少必需的结构体字段: %s", fieldName))
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
// 普通参数验证是否存在
|
||
if _, exists := params[paramName]; !exists {
|
||
errors = append(errors, fmt.Sprintf("缺少必需参数: %s", paramName))
|
||
}
|
||
}
|
||
}
|
||
|
||
// 如果参数存在,验证其类型
|
||
if value, exists := params[paramName]; exists && info["type"] != nil {
|
||
expectedType := info["type"].(string)
|
||
// 根据期望的类型验证参数
|
||
switch expectedType {
|
||
case "string":
|
||
if _, ok := value.(string); !ok {
|
||
errors = append(errors, fmt.Sprintf("参数 %s 类型错误,应为字符串", paramName))
|
||
}
|
||
case "integer":
|
||
// 支持多种整数类型
|
||
switch value.(type) {
|
||
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
|
||
// 这些类型都是可接受的
|
||
default:
|
||
errors = append(errors, fmt.Sprintf("参数 %s 类型错误,应为整数", paramName))
|
||
}
|
||
case "float":
|
||
switch value.(type) {
|
||
case float32, float64:
|
||
// 这些类型是可接受的
|
||
default:
|
||
errors = append(errors, fmt.Sprintf("参数 %s 类型错误,应为浮点数", paramName))
|
||
}
|
||
case "boolean":
|
||
if _, ok := value.(bool); !ok {
|
||
errors = append(errors, fmt.Sprintf("参数 %s 类型错误,应为布尔值", paramName))
|
||
}
|
||
case "array":
|
||
if _, ok := value.([]interface{}); !ok {
|
||
errors = append(errors, fmt.Sprintf("参数 %s 类型错误,应为数组", paramName))
|
||
}
|
||
case "object":
|
||
if _, ok := value.(map[string]interface{}); !ok {
|
||
errors = append(errors, fmt.Sprintf("参数 %s 类型错误,应为对象", paramName))
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 如果有错误,返回组合的错误信息
|
||
if len(errors) > 0 {
|
||
return fmt.Errorf("参数验证失败: %s", strings.Join(errors, "; "))
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// ExecuteAction 执行指定的动作
|
||
func (h *PluginHelper) ExecuteAction(ctx context.Context, action string, params map[string]interface{}) (interface{}, error) {
|
||
// 转换为小写以实现不区分大小写的匹配
|
||
action = strings.ToLower(action)
|
||
|
||
method, exists := h.methods[action]
|
||
if !exists {
|
||
return nil, fmt.Errorf("未知的操作: %s", action)
|
||
}
|
||
|
||
// 获取操作的参数信息并验证参数
|
||
opInfo, err := h.GetParameterInfo(action)
|
||
if err == nil {
|
||
// 验证参数
|
||
if err := ValidateParams(opInfo, params); err != nil {
|
||
return nil, err
|
||
}
|
||
}
|
||
|
||
paramTypes := h.methodParams[action]
|
||
|
||
// 准备参数
|
||
var args []reflect.Value
|
||
|
||
// 添加接收者参数
|
||
args = append(args, reflect.ValueOf(h.instance))
|
||
|
||
// 处理context参数
|
||
if len(paramTypes) > 0 && paramTypes[0].String() == "context.Context" {
|
||
args = append(args, reflect.ValueOf(ctx))
|
||
paramTypes = paramTypes[1:] // 移除已处理的context参数
|
||
}
|
||
|
||
// 处理其他参数
|
||
for i, paramType := range paramTypes {
|
||
paramName := fmt.Sprintf("arg%d", i)
|
||
|
||
// 如果是结构体参数,尝试将整个params映射转换为该结构体
|
||
if paramType.Kind() == reflect.Struct {
|
||
structValue := reflect.New(paramType).Elem()
|
||
if err := mapToStruct(params, structValue); err != nil {
|
||
return nil, fmt.Errorf("转换参数失败: %v", err)
|
||
}
|
||
args = append(args, structValue)
|
||
continue
|
||
}
|
||
|
||
// 从params中获取参数
|
||
paramValue, ok := params[paramName]
|
||
if !ok {
|
||
// 尝试使用参数类型名称作为键
|
||
typeName := paramType.Name()
|
||
paramValue, ok = params[strings.ToLower(typeName)]
|
||
|
||
if !ok {
|
||
return nil, fmt.Errorf("缺少必需参数: %s", paramName)
|
||
}
|
||
}
|
||
|
||
// 转换参数类型
|
||
convertedValue, err := convertParamValue(paramValue, paramType)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
args = append(args, convertedValue)
|
||
}
|
||
|
||
// 调用方法
|
||
result := method.Func.Call(args)
|
||
|
||
// 处理返回值
|
||
if len(result) == 0 {
|
||
return nil, nil
|
||
} else if len(result) == 1 {
|
||
return result[0].Interface(), nil
|
||
} else {
|
||
// 处理多个返回值,通常最后一个是error
|
||
lastIndex := len(result) - 1
|
||
if result[lastIndex].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
|
||
if !result[lastIndex].IsNil() {
|
||
return nil, result[lastIndex].Interface().(error)
|
||
}
|
||
|
||
if lastIndex == 0 {
|
||
return nil, nil
|
||
}
|
||
return result[lastIndex-1].Interface(), nil
|
||
}
|
||
|
||
// 将所有返回值打包成一个映射
|
||
resultMap := make(map[string]interface{})
|
||
for i, v := range result {
|
||
resultMap[fmt.Sprintf("result%d", i)] = v.Interface()
|
||
}
|
||
return resultMap, nil
|
||
}
|
||
}
|
||
|
||
// mapToStruct 将map转换为结构体
|
||
func mapToStruct(m map[string]interface{}, structValue reflect.Value) error {
|
||
structType := structValue.Type()
|
||
|
||
for i := 0; i < structType.NumField(); i++ {
|
||
field := structType.Field(i)
|
||
fieldValue := structValue.Field(i)
|
||
|
||
if !fieldValue.CanSet() {
|
||
continue
|
||
}
|
||
|
||
// 尝试不同的命名方式
|
||
fieldName := field.Name
|
||
jsonTag := field.Tag.Get("json")
|
||
if jsonTag != "" && jsonTag != "-" {
|
||
parts := strings.Split(jsonTag, ",")
|
||
fieldName = parts[0]
|
||
}
|
||
|
||
// 检查不同大小写
|
||
value, ok := m[fieldName]
|
||
if !ok {
|
||
value, ok = m[strings.ToLower(fieldName)]
|
||
}
|
||
if !ok {
|
||
continue // 跳过未找到的字段
|
||
}
|
||
|
||
// 转换并设置字段值
|
||
convertedValue, err := convertParamValue(value, field.Type)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
fieldValue.Set(convertedValue)
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// convertParamValue 将接口值转换为指定类型
|
||
func convertParamValue(value interface{}, targetType reflect.Type) (reflect.Value, error) {
|
||
// 处理nil值
|
||
if value == nil {
|
||
return reflect.Zero(targetType), nil
|
||
}
|
||
|
||
valueType := reflect.TypeOf(value)
|
||
|
||
// 如果类型已经匹配,直接返回
|
||
if valueType.AssignableTo(targetType) {
|
||
return reflect.ValueOf(value), nil
|
||
}
|
||
|
||
// 类型转换
|
||
switch targetType.Kind() {
|
||
case reflect.String:
|
||
return reflect.ValueOf(fmt.Sprintf("%v", value)), nil
|
||
|
||
case reflect.Bool:
|
||
switch v := value.(type) {
|
||
case bool:
|
||
return reflect.ValueOf(v), nil
|
||
case string:
|
||
b, err := strconv.ParseBool(v)
|
||
if err != nil {
|
||
return reflect.Value{}, fmt.Errorf("无法将 %v 转换为布尔值", value)
|
||
}
|
||
return reflect.ValueOf(b), nil
|
||
case float64:
|
||
return reflect.ValueOf(v != 0), nil
|
||
}
|
||
|
||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
var intVal int64
|
||
switch v := value.(type) {
|
||
case int:
|
||
intVal = int64(v)
|
||
case int8:
|
||
intVal = int64(v)
|
||
case int16:
|
||
intVal = int64(v)
|
||
case int32:
|
||
intVal = int64(v)
|
||
case int64:
|
||
intVal = v
|
||
case float32:
|
||
intVal = int64(v)
|
||
case float64:
|
||
intVal = int64(v)
|
||
case string:
|
||
var err error
|
||
intVal, err = strconv.ParseInt(v, 10, 64)
|
||
if err != nil {
|
||
return reflect.Value{}, fmt.Errorf("无法将 %v 转换为整数", value)
|
||
}
|
||
default:
|
||
return reflect.Value{}, fmt.Errorf("无法将 %v 转换为整数", value)
|
||
}
|
||
|
||
switch targetType.Kind() {
|
||
case reflect.Int:
|
||
return reflect.ValueOf(int(intVal)), nil
|
||
case reflect.Int8:
|
||
return reflect.ValueOf(int8(intVal)), nil
|
||
case reflect.Int16:
|
||
return reflect.ValueOf(int16(intVal)), nil
|
||
case reflect.Int32:
|
||
return reflect.ValueOf(int32(intVal)), nil
|
||
case reflect.Int64:
|
||
return reflect.ValueOf(intVal), nil
|
||
}
|
||
|
||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||
var uintVal uint64
|
||
switch v := value.(type) {
|
||
case uint:
|
||
uintVal = uint64(v)
|
||
case uint8:
|
||
uintVal = uint64(v)
|
||
case uint16:
|
||
uintVal = uint64(v)
|
||
case uint32:
|
||
uintVal = uint64(v)
|
||
case uint64:
|
||
uintVal = v
|
||
case int:
|
||
if v < 0 {
|
||
return reflect.Value{}, fmt.Errorf("无法将负数 %v 转换为无符号整数", value)
|
||
}
|
||
uintVal = uint64(v)
|
||
case float64:
|
||
if v < 0 {
|
||
return reflect.Value{}, fmt.Errorf("无法将负数 %v 转换为无符号整数", value)
|
||
}
|
||
uintVal = uint64(v)
|
||
case string:
|
||
var err error
|
||
uintVal, err = strconv.ParseUint(v, 10, 64)
|
||
if err != nil {
|
||
return reflect.Value{}, fmt.Errorf("无法将 %v 转换为无符号整数", value)
|
||
}
|
||
default:
|
||
return reflect.Value{}, fmt.Errorf("无法将 %v 转换为无符号整数", value)
|
||
}
|
||
|
||
switch targetType.Kind() {
|
||
case reflect.Uint:
|
||
return reflect.ValueOf(uint(uintVal)), nil
|
||
case reflect.Uint8:
|
||
return reflect.ValueOf(uint8(uintVal)), nil
|
||
case reflect.Uint16:
|
||
return reflect.ValueOf(uint16(uintVal)), nil
|
||
case reflect.Uint32:
|
||
return reflect.ValueOf(uint32(uintVal)), nil
|
||
case reflect.Uint64:
|
||
return reflect.ValueOf(uintVal), nil
|
||
}
|
||
|
||
case reflect.Float32, reflect.Float64:
|
||
var floatVal float64
|
||
switch v := value.(type) {
|
||
case float32:
|
||
floatVal = float64(v)
|
||
case float64:
|
||
floatVal = v
|
||
case int:
|
||
floatVal = float64(v)
|
||
case int64:
|
||
floatVal = float64(v)
|
||
case string:
|
||
var err error
|
||
floatVal, err = strconv.ParseFloat(v, 64)
|
||
if err != nil {
|
||
return reflect.Value{}, fmt.Errorf("无法将 %v 转换为浮点数", value)
|
||
}
|
||
default:
|
||
return reflect.Value{}, fmt.Errorf("无法将 %v 转换为浮点数", value)
|
||
}
|
||
|
||
if targetType.Kind() == reflect.Float32 {
|
||
return reflect.ValueOf(float32(floatVal)), nil
|
||
}
|
||
return reflect.ValueOf(floatVal), nil
|
||
|
||
case reflect.Slice:
|
||
// 处理切片类型
|
||
srcVal := reflect.ValueOf(value)
|
||
if srcVal.Kind() == reflect.Slice {
|
||
// 创建目标类型的新切片
|
||
elemType := targetType.Elem()
|
||
newSlice := reflect.MakeSlice(targetType, srcVal.Len(), srcVal.Cap())
|
||
|
||
// 转换每个元素
|
||
for i := 0; i < srcVal.Len(); i++ {
|
||
elemValue, err := convertParamValue(srcVal.Index(i).Interface(), elemType)
|
||
if err != nil {
|
||
return reflect.Value{}, err
|
||
}
|
||
newSlice.Index(i).Set(elemValue)
|
||
}
|
||
return newSlice, nil
|
||
}
|
||
|
||
case reflect.Map:
|
||
// 处理映射类型
|
||
srcVal := reflect.ValueOf(value)
|
||
if srcVal.Kind() == reflect.Map {
|
||
keyType := targetType.Key()
|
||
elemType := targetType.Elem()
|
||
newMap := reflect.MakeMap(targetType)
|
||
|
||
iter := srcVal.MapRange()
|
||
for iter.Next() {
|
||
k := iter.Key()
|
||
v := iter.Value()
|
||
|
||
newKey, err := convertParamValue(k.Interface(), keyType)
|
||
if err != nil {
|
||
return reflect.Value{}, err
|
||
}
|
||
|
||
newValue, err := convertParamValue(v.Interface(), elemType)
|
||
if err != nil {
|
||
return reflect.Value{}, err
|
||
}
|
||
|
||
newMap.SetMapIndex(newKey, newValue)
|
||
}
|
||
|
||
return newMap, nil
|
||
}
|
||
|
||
case reflect.Ptr:
|
||
// 处理指针类型
|
||
elemType := targetType.Elem()
|
||
elemValue, err := convertParamValue(value, elemType)
|
||
if err != nil {
|
||
return reflect.Value{}, err
|
||
}
|
||
|
||
ptrValue := reflect.New(elemType)
|
||
ptrValue.Elem().Set(elemValue)
|
||
return ptrValue, nil
|
||
}
|
||
|
||
return reflect.Value{}, fmt.Errorf("不支持将 %T 类型转换为 %s", value, targetType)
|
||
}
|
||
|
||
// GetParameterInfo 获取操作的参数信息
|
||
func (h *PluginHelper) GetParameterInfo(action string) (map[string]interface{}, error) {
|
||
action = strings.ToLower(action)
|
||
method, exists := h.methods[action]
|
||
if !exists {
|
||
return nil, fmt.Errorf("未知的操作: %s", action)
|
||
}
|
||
|
||
paramTypes := h.methodParams[action]
|
||
returnTypes := h.methodRetValues[action]
|
||
|
||
result := map[string]interface{}{
|
||
"name": action,
|
||
"description": fmt.Sprintf("%s 操作", method.Name),
|
||
"parameters": make(map[string]interface{}),
|
||
"returns": make(map[string]interface{}),
|
||
}
|
||
|
||
// 处理参数信息
|
||
paramsInfo := make(map[string]interface{})
|
||
|
||
// 首先检查是否有context参数
|
||
hasContext := false
|
||
if len(paramTypes) > 0 && paramTypes[0].String() == "context.Context" {
|
||
hasContext = true
|
||
result["hasContext"] = true
|
||
paramTypes = paramTypes[1:] // 跳过context参数
|
||
}
|
||
|
||
for i, paramType := range paramTypes {
|
||
// 如果是结构体参数,展开其字段
|
||
if paramType.Kind() == reflect.Struct {
|
||
structInfo := getStructInfo(paramType)
|
||
structInfo["position"] = i + 1 // 考虑到接收者和可能的context
|
||
if hasContext {
|
||
structInfo["position"] = i + 2
|
||
}
|
||
paramsInfo[paramType.Name()] = structInfo
|
||
} else {
|
||
// 基本类型参数
|
||
paramName := fmt.Sprintf("arg%d", i)
|
||
typeInfo := getTypeInfo(paramType)
|
||
typeInfo["position"] = i + 1 // 考虑到接收者
|
||
if hasContext {
|
||
typeInfo["position"] = i + 2
|
||
}
|
||
paramsInfo[paramName] = typeInfo
|
||
}
|
||
}
|
||
result["parameters"] = paramsInfo
|
||
|
||
// 处理返回值信息
|
||
returnsInfo := make(map[string]interface{})
|
||
for i, returnType := range returnTypes {
|
||
returnName := fmt.Sprintf("return%d", i)
|
||
if i == len(returnTypes)-1 && returnType.String() == "error" {
|
||
returnName = "error"
|
||
} else if i == 0 && len(returnTypes) == 2 && returnTypes[1].String() == "error" {
|
||
returnName = "result"
|
||
}
|
||
returnsInfo[returnName] = getTypeInfo(returnType)
|
||
}
|
||
result["returns"] = returnsInfo
|
||
|
||
return result, nil
|
||
}
|
||
|
||
// getStructInfo 获取结构体类型的详细信息
|
||
func getStructInfo(t reflect.Type) map[string]interface{} {
|
||
info := map[string]interface{}{
|
||
"type": "struct",
|
||
"name": t.Name(),
|
||
"package": t.PkgPath(),
|
||
"fields": make(map[string]interface{}),
|
||
"fieldCount": t.NumField(),
|
||
}
|
||
|
||
fields := make(map[string]interface{})
|
||
for i := 0; i < t.NumField(); i++ {
|
||
field := t.Field(i)
|
||
|
||
// 跳过非导出字段
|
||
if field.PkgPath != "" {
|
||
continue
|
||
}
|
||
|
||
fieldName := field.Name
|
||
jsonTag := field.Tag.Get("json")
|
||
if jsonTag != "" && jsonTag != "-" {
|
||
parts := strings.Split(jsonTag, ",")
|
||
if parts[0] != "" {
|
||
fieldName = parts[0]
|
||
}
|
||
}
|
||
|
||
fieldInfo := getTypeInfo(field.Type)
|
||
fieldInfo["name"] = field.Name
|
||
fieldInfo["jsonName"] = fieldName
|
||
fieldInfo["position"] = i
|
||
fieldInfo["tags"] = string(field.Tag)
|
||
|
||
fields[fieldName] = fieldInfo
|
||
}
|
||
info["fields"] = fields
|
||
|
||
return info
|
||
}
|
||
|
||
// getTypeInfo 获取类型的基本信息
|
||
func getTypeInfo(t reflect.Type) map[string]interface{} {
|
||
info := map[string]interface{}{
|
||
"typeName": t.String(),
|
||
"kind": t.Kind().String(),
|
||
"type": typeKindToString(t.Kind()),
|
||
}
|
||
|
||
// 为不同类型添加特定信息
|
||
switch t.Kind() {
|
||
case reflect.Slice, reflect.Array:
|
||
info["elemType"] = getTypeInfo(t.Elem())
|
||
case reflect.Map:
|
||
info["keyType"] = getTypeInfo(t.Key())
|
||
info["valueType"] = getTypeInfo(t.Elem())
|
||
case reflect.Ptr:
|
||
info["elemType"] = getTypeInfo(t.Elem())
|
||
case reflect.Struct:
|
||
// 对于结构体,提供简略信息
|
||
info["structName"] = t.Name()
|
||
info["package"] = t.PkgPath()
|
||
info["fieldCount"] = t.NumField()
|
||
}
|
||
|
||
return info
|
||
}
|
||
|
||
// typeKindToString 将类型Kind转换为字符串表示
|
||
func typeKindToString(kind reflect.Kind) string {
|
||
switch kind {
|
||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
return "integer"
|
||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||
return "unsigned integer"
|
||
case reflect.Float32, reflect.Float64:
|
||
return "float"
|
||
case reflect.Bool:
|
||
return "boolean"
|
||
case reflect.String:
|
||
return "string"
|
||
case reflect.Slice, reflect.Array:
|
||
return "array"
|
||
case reflect.Map:
|
||
return "map"
|
||
case reflect.Struct:
|
||
return "object"
|
||
case reflect.Ptr:
|
||
return "pointer"
|
||
case reflect.Interface:
|
||
return "interface"
|
||
default:
|
||
return kind.String()
|
||
}
|
||
}
|
||
|
||
// BasePluginImpl 提供插件接口的基本实现,用于适配Plugin接口
|
||
// 这个结构体包装了BasePlugin,以便兼容context参数
|
||
type BasePluginImpl struct {
|
||
*BasePlugin
|
||
helper *PluginHelper // 添加插件辅助器
|
||
}
|
||
|
||
// NewPlugin 创建一个基本插件实现,带有插件类型
|
||
func NewPlugin(name, version, description, author string, pluginType PluginType) *BasePluginImpl {
|
||
plugin := &BasePluginImpl{
|
||
BasePlugin: NewBasePlugin(name, version, description, author, pluginType),
|
||
}
|
||
plugin.helper = NewPluginHelper(plugin)
|
||
return plugin
|
||
}
|
||
|
||
// NewPluginWithDefaultType 创建一个基本插件实现,使用默认的通用插件类型
|
||
func NewPluginWithDefaultType(name, version, description, author string) *BasePluginImpl {
|
||
plugin := &BasePluginImpl{
|
||
BasePlugin: NewBasePluginWithDefaultType(name, version, description, author),
|
||
}
|
||
plugin.helper = NewPluginHelper(plugin)
|
||
return plugin
|
||
}
|
||
|
||
// Init 适配Init方法以支持context参数
|
||
func (p *BasePluginImpl) Init(ctx context.Context, config map[string]interface{}) error {
|
||
return p.BasePlugin.Init(config)
|
||
}
|
||
|
||
// Start 适配Start方法以支持context参数
|
||
func (p *BasePluginImpl) Start(ctx context.Context) error {
|
||
return p.BasePlugin.Start()
|
||
}
|
||
|
||
// Stop 适配Stop方法以支持context参数
|
||
func (p *BasePluginImpl) Stop(ctx context.Context) error {
|
||
return p.BasePlugin.Stop()
|
||
}
|
||
|
||
// Execute 通过辅助器自动执行插件方法
|
||
func (p *BasePluginImpl) Execute(ctx context.Context, action string, params map[string]interface{}) (interface{}, error) {
|
||
// 首先尝试通过辅助器执行方法
|
||
result, err := p.helper.ExecuteAction(ctx, action, params)
|
||
if err == nil {
|
||
return result, nil
|
||
}
|
||
|
||
// 如果辅助器执行失败,检查错误类型
|
||
if strings.Contains(err.Error(), "未知的操作") {
|
||
// 回退到基础实现
|
||
return p.BasePlugin.Execute(action, params)
|
||
}
|
||
|
||
return nil, err
|
||
}
|
||
|
||
// GetAvailableActions 获取插件支持的所有操作
|
||
func (p *BasePluginImpl) GetAvailableActions() []string {
|
||
return p.helper.GetAvailableActions()
|
||
}
|
||
|
||
// GetOperationInfo 获取操作的参数信息
|
||
func (p *BasePluginImpl) GetOperationInfo(operation string) (map[string]interface{}, error) {
|
||
return p.helper.GetParameterInfo(operation)
|
||
}
|
||
|
||
// GetAllOperations 获取所有操作及其参数信息
|
||
func (p *BasePluginImpl) GetAllOperations() map[string]map[string]interface{} {
|
||
operations := make(map[string]map[string]interface{})
|
||
for _, action := range p.helper.GetAvailableActions() {
|
||
info, err := p.helper.GetParameterInfo(action)
|
||
if err == nil {
|
||
operations[action] = info
|
||
}
|
||
}
|
||
return operations
|
||
}
|
||
|
||
// 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)
|
||
}
|
||
|
||
// 使用反射检查插件对象
|
||
pluginValue := reflect.ValueOf(symPlugin)
|
||
fmt.Printf("加载插件: %s, 类型: %s\n", path, pluginValue.Type())
|
||
|
||
// 查找基本字段或方法
|
||
var pluginName, pluginVersion, pluginAuthor, pluginDesc string
|
||
var pluginType PluginType = PluginTypeGeneral
|
||
var enabled = true
|
||
|
||
// 直接检查方法
|
||
// 尝试通过方法获取信息
|
||
nameFound := false
|
||
if nameMethod := pluginValue.MethodByName("Name"); nameMethod.IsValid() {
|
||
results := nameMethod.Call(nil)
|
||
if len(results) > 0 && results[0].Kind() == reflect.String {
|
||
pluginName = results[0].String()
|
||
nameFound = true
|
||
}
|
||
}
|
||
|
||
if versionMethod := pluginValue.MethodByName("Version"); versionMethod.IsValid() {
|
||
results := versionMethod.Call(nil)
|
||
if len(results) > 0 && results[0].Kind() == reflect.String {
|
||
pluginVersion = results[0].String()
|
||
}
|
||
}
|
||
|
||
if descMethod := pluginValue.MethodByName("Description"); descMethod.IsValid() {
|
||
results := descMethod.Call(nil)
|
||
if len(results) > 0 && results[0].Kind() == reflect.String {
|
||
pluginDesc = results[0].String()
|
||
}
|
||
}
|
||
|
||
if authorMethod := pluginValue.MethodByName("Author"); authorMethod.IsValid() {
|
||
results := authorMethod.Call(nil)
|
||
if len(results) > 0 && results[0].Kind() == reflect.String {
|
||
pluginAuthor = results[0].String()
|
||
}
|
||
}
|
||
|
||
if typeMethod := pluginValue.MethodByName("Type"); typeMethod.IsValid() {
|
||
results := typeMethod.Call(nil)
|
||
if len(results) > 0 {
|
||
// 尝试匹配插件类型
|
||
typeStr := fmt.Sprint(results[0].Interface())
|
||
switch typeStr {
|
||
case "storage":
|
||
pluginType = PluginTypeStorage
|
||
case "security":
|
||
pluginType = PluginTypeSecurity
|
||
case "network":
|
||
pluginType = PluginTypeNetwork
|
||
case "utils":
|
||
pluginType = PluginTypeUtils
|
||
case "hardware":
|
||
pluginType = PluginTypeHardware
|
||
case "ui":
|
||
pluginType = PluginTypeUI
|
||
}
|
||
}
|
||
}
|
||
|
||
// 直接检查字段(仅在方法不可用时)
|
||
if !nameFound && pluginValue.Kind() == reflect.Ptr && !pluginValue.IsNil() {
|
||
elemValue := pluginValue.Elem()
|
||
|
||
// 检查elemValue是否为结构体
|
||
if elemValue.Kind() == reflect.Struct {
|
||
// 检查是否有name字段
|
||
if nameField := elemValue.FieldByName("name"); nameField.IsValid() && nameField.Kind() == reflect.String {
|
||
pluginName = nameField.String()
|
||
}
|
||
|
||
// 检查是否有version字段
|
||
if versionField := elemValue.FieldByName("version"); versionField.IsValid() && versionField.Kind() == reflect.String {
|
||
pluginVersion = versionField.String()
|
||
}
|
||
|
||
// 检查是否有description字段
|
||
if descField := elemValue.FieldByName("description"); descField.IsValid() && descField.Kind() == reflect.String {
|
||
pluginDesc = descField.String()
|
||
}
|
||
|
||
// 检查是否有author字段
|
||
if authorField := elemValue.FieldByName("author"); authorField.IsValid() && authorField.Kind() == reflect.String {
|
||
pluginAuthor = authorField.String()
|
||
}
|
||
|
||
// 检查是否有pluginType字段
|
||
if typeField := elemValue.FieldByName("pluginType"); typeField.IsValid() {
|
||
// 转换为字符串并尝试匹配已知类型
|
||
typeStr := fmt.Sprint(typeField.Interface())
|
||
switch typeStr {
|
||
case "storage":
|
||
pluginType = PluginTypeStorage
|
||
case "security":
|
||
pluginType = PluginTypeSecurity
|
||
case "network":
|
||
pluginType = PluginTypeNetwork
|
||
case "utils":
|
||
pluginType = PluginTypeUtils
|
||
case "hardware":
|
||
pluginType = PluginTypeHardware
|
||
case "ui":
|
||
pluginType = PluginTypeUI
|
||
}
|
||
}
|
||
|
||
// 检查是否有enabled字段
|
||
if enabledField := elemValue.FieldByName("enabled"); enabledField.IsValid() && enabledField.Kind() == reflect.Bool {
|
||
enabled = enabledField.Bool()
|
||
}
|
||
}
|
||
}
|
||
|
||
// 如果名称仍为空,则使用文件名
|
||
if pluginName == "" {
|
||
// 从路径中提取文件名并去掉扩展名
|
||
fileName := filepath.Base(path)
|
||
pluginName = strings.TrimSuffix(fileName, filepath.Ext(fileName))
|
||
}
|
||
|
||
fmt.Printf("创建适配器插件: 名称=%s, 版本=%s, 作者=%s, 类型=%s\n",
|
||
pluginName, pluginVersion, pluginAuthor, pluginType)
|
||
|
||
// 创建一个自定义插件结构体
|
||
customPlugin := &DynamicPlugin{
|
||
original: symPlugin,
|
||
name: pluginName,
|
||
version: pluginVersion,
|
||
description: pluginDesc,
|
||
author: pluginAuthor,
|
||
pluginType: pluginType,
|
||
enabled: enabled,
|
||
}
|
||
|
||
// 检查插件名称是否已存在
|
||
pm.mu.Lock()
|
||
defer pm.mu.Unlock()
|
||
|
||
if _, exists := pm.plugins[customPlugin.Name()]; exists {
|
||
return fmt.Errorf("插件 %s 已存在", customPlugin.Name())
|
||
}
|
||
|
||
// 设置插件启用状态
|
||
if config, exists := pm.configs[customPlugin.Name()]; exists {
|
||
if enabled, ok := config["enabled"].(bool); ok {
|
||
customPlugin.enabled = enabled
|
||
}
|
||
}
|
||
|
||
// 注册插件
|
||
pm.registerPlugin(customPlugin)
|
||
fmt.Printf("已成功注册插件: %s\n", customPlugin.Name())
|
||
return nil
|
||
}
|
||
|
||
// DynamicPlugin 完全动态的插件实现
|
||
type DynamicPlugin struct {
|
||
original interface{}
|
||
name string
|
||
version string
|
||
description string
|
||
author string
|
||
pluginType PluginType
|
||
enabled bool
|
||
}
|
||
|
||
// Name 返回插件名称
|
||
func (p *DynamicPlugin) Name() string {
|
||
return p.name
|
||
}
|
||
|
||
// Version 返回插件版本
|
||
func (p *DynamicPlugin) Version() string {
|
||
return p.version
|
||
}
|
||
|
||
// Description 返回插件描述
|
||
func (p *DynamicPlugin) Description() string {
|
||
return p.description
|
||
}
|
||
|
||
// Author 返回插件作者
|
||
func (p *DynamicPlugin) Author() string {
|
||
return p.author
|
||
}
|
||
|
||
// Type 返回插件类型
|
||
func (p *DynamicPlugin) Type() PluginType {
|
||
return p.pluginType
|
||
}
|
||
|
||
// IsEnabled 返回插件是否启用
|
||
func (p *DynamicPlugin) IsEnabled() bool {
|
||
return p.enabled
|
||
}
|
||
|
||
// SetEnabled 设置插件启用状态
|
||
func (p *DynamicPlugin) SetEnabled(enabled bool) {
|
||
p.enabled = enabled
|
||
|
||
// 尝试调用原始插件的SetEnabled方法
|
||
method := reflect.ValueOf(p.original).MethodByName("SetEnabled")
|
||
if method.IsValid() {
|
||
method.Call([]reflect.Value{reflect.ValueOf(enabled)})
|
||
}
|
||
}
|
||
|
||
// Init 初始化插件
|
||
func (p *DynamicPlugin) Init(ctx context.Context, config map[string]interface{}) error {
|
||
method := reflect.ValueOf(p.original).MethodByName("Init")
|
||
if !method.IsValid() {
|
||
return nil // 如果方法不存在,就不做任何事情
|
||
}
|
||
|
||
// 确定方法参数数量和类型
|
||
methodType := method.Type()
|
||
numParams := methodType.NumIn()
|
||
|
||
// 准备参数
|
||
var args []reflect.Value
|
||
|
||
// 对于不同参数数量的处理
|
||
switch numParams {
|
||
case 0:
|
||
// 无参数
|
||
case 1:
|
||
// 只有一个参数,可能是配置
|
||
args = append(args, reflect.ValueOf(config))
|
||
case 2:
|
||
// 两个参数,可能是上下文和配置
|
||
args = append(args, reflect.ValueOf(ctx), reflect.ValueOf(config))
|
||
default:
|
||
// 不支持更多参数
|
||
return fmt.Errorf("不支持的Init方法参数数量: %d", numParams)
|
||
}
|
||
|
||
// 调用方法
|
||
results := method.Call(args)
|
||
|
||
// 处理返回值
|
||
if len(results) > 0 && results[0].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
|
||
if !results[0].IsNil() {
|
||
return results[0].Interface().(error)
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// Start 启动插件
|
||
func (p *DynamicPlugin) Start(ctx context.Context) error {
|
||
method := reflect.ValueOf(p.original).MethodByName("Start")
|
||
if !method.IsValid() {
|
||
return nil // 如果方法不存在,就不做任何事情
|
||
}
|
||
|
||
// 确定方法参数数量和类型
|
||
methodType := method.Type()
|
||
numParams := methodType.NumIn()
|
||
|
||
// 准备参数
|
||
var args []reflect.Value
|
||
|
||
// 对于不同参数数量的处理
|
||
switch numParams {
|
||
case 0:
|
||
// 无参数
|
||
case 1:
|
||
// 一个参数,可能是上下文
|
||
args = append(args, reflect.ValueOf(ctx))
|
||
default:
|
||
// 不支持更多参数
|
||
return fmt.Errorf("不支持的Start方法参数数量: %d", numParams)
|
||
}
|
||
|
||
// 调用方法
|
||
results := method.Call(args)
|
||
|
||
// 处理返回值
|
||
if len(results) > 0 && results[0].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
|
||
if !results[0].IsNil() {
|
||
return results[0].Interface().(error)
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// Stop 停止插件
|
||
func (p *DynamicPlugin) Stop(ctx context.Context) error {
|
||
method := reflect.ValueOf(p.original).MethodByName("Stop")
|
||
if !method.IsValid() {
|
||
return nil // 如果方法不存在,就不做任何事情
|
||
}
|
||
|
||
// 确定方法参数数量和类型
|
||
methodType := method.Type()
|
||
numParams := methodType.NumIn()
|
||
|
||
// 准备参数
|
||
var args []reflect.Value
|
||
|
||
// 对于不同参数数量的处理
|
||
switch numParams {
|
||
case 0:
|
||
// 无参数
|
||
case 1:
|
||
// 一个参数,可能是上下文
|
||
args = append(args, reflect.ValueOf(ctx))
|
||
default:
|
||
// 不支持更多参数
|
||
return fmt.Errorf("不支持的Stop方法参数数量: %d", numParams)
|
||
}
|
||
|
||
// 调用方法
|
||
results := method.Call(args)
|
||
|
||
// 处理返回值
|
||
if len(results) > 0 && results[0].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
|
||
if !results[0].IsNil() {
|
||
return results[0].Interface().(error)
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// Execute 执行插件功能
|
||
func (p *DynamicPlugin) Execute(ctx context.Context, action string, params map[string]interface{}) (interface{}, error) {
|
||
method := reflect.ValueOf(p.original).MethodByName("Execute")
|
||
if !method.IsValid() {
|
||
return nil, fmt.Errorf("插件不支持Execute方法")
|
||
}
|
||
|
||
// 确定方法参数数量和类型
|
||
methodType := method.Type()
|
||
numParams := methodType.NumIn()
|
||
|
||
// 准备参数
|
||
var args []reflect.Value
|
||
|
||
// 对于不同参数数量的处理
|
||
switch numParams {
|
||
case 2:
|
||
// 两个参数,可能是action和params
|
||
args = append(args, reflect.ValueOf(action), reflect.ValueOf(params))
|
||
case 3:
|
||
// 三个参数,可能是ctx、action和params
|
||
args = append(args, reflect.ValueOf(ctx), reflect.ValueOf(action), reflect.ValueOf(params))
|
||
default:
|
||
// 不支持其他参数数量
|
||
return nil, fmt.Errorf("不支持的Execute方法参数数量: %d", numParams)
|
||
}
|
||
|
||
// 调用方法
|
||
results := method.Call(args)
|
||
|
||
// 处理返回值
|
||
var result interface{}
|
||
var err error
|
||
|
||
switch len(results) {
|
||
case 1:
|
||
// 只有一个返回值,检查是否为错误
|
||
if results[0].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
|
||
if !results[0].IsNil() {
|
||
err = results[0].Interface().(error)
|
||
}
|
||
} else {
|
||
result = results[0].Interface()
|
||
}
|
||
case 2:
|
||
// 两个返回值,第一个是结果,第二个是错误
|
||
if !results[0].IsNil() {
|
||
result = results[0].Interface()
|
||
}
|
||
|
||
if results[1].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
|
||
if !results[1].IsNil() {
|
||
err = results[1].Interface().(error)
|
||
}
|
||
}
|
||
}
|
||
|
||
return result, err
|
||
}
|
||
|
||
// GetOperationInfo 获取操作的参数信息
|
||
func (p *DynamicPlugin) GetOperationInfo(operation string) (map[string]interface{}, error) {
|
||
method := reflect.ValueOf(p.original).MethodByName("GetOperationInfo")
|
||
if !method.IsValid() {
|
||
return map[string]interface{}{}, nil
|
||
}
|
||
|
||
results := method.Call([]reflect.Value{reflect.ValueOf(operation)})
|
||
|
||
var result map[string]interface{}
|
||
var err error
|
||
|
||
if len(results) > 0 && !results[0].IsNil() {
|
||
if m, ok := results[0].Interface().(map[string]interface{}); ok {
|
||
result = m
|
||
} else {
|
||
result = map[string]interface{}{}
|
||
}
|
||
} else {
|
||
result = map[string]interface{}{}
|
||
}
|
||
|
||
if len(results) > 1 && results[1].Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) {
|
||
if !results[1].IsNil() {
|
||
err = results[1].Interface().(error)
|
||
}
|
||
}
|
||
|
||
return result, err
|
||
}
|
||
|
||
// GetAllOperations 获取所有操作及其参数信息
|
||
func (p *DynamicPlugin) GetAllOperations() map[string]map[string]interface{} {
|
||
method := reflect.ValueOf(p.original).MethodByName("GetAllOperations")
|
||
if !method.IsValid() {
|
||
return map[string]map[string]interface{}{}
|
||
}
|
||
|
||
results := method.Call(nil)
|
||
|
||
if len(results) > 0 && !results[0].IsNil() {
|
||
if m, ok := results[0].Interface().(map[string]map[string]interface{}); ok {
|
||
return m
|
||
}
|
||
}
|
||
|
||
return map[string]map[string]interface{}{}
|
||
}
|
||
|
||
// 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
|
||
}
|
||
|
||
// ExecutePlugin 执行指定插件的操作
|
||
func (pm *PluginManager) ExecutePlugin(ctx context.Context, name string, action string, params map[string]interface{}) (interface{}, error) {
|
||
pm.mu.RLock()
|
||
defer pm.mu.RUnlock()
|
||
|
||
plugin, exists := pm.plugins[name]
|
||
if !exists {
|
||
return nil, fmt.Errorf("插件 %s 不存在", name)
|
||
}
|
||
|
||
if !plugin.IsEnabled() {
|
||
return nil, fmt.Errorf("插件 %s 已禁用", name)
|
||
}
|
||
|
||
return plugin.Execute(ctx, action, params)
|
||
}
|
||
|
||
// ExecutePluginsByType 对指定类型的所有插件执行操作
|
||
func (pm *PluginManager) ExecutePluginsByType(ctx context.Context, pluginType PluginType, action string, params map[string]interface{}) map[string]interface{} {
|
||
pm.mu.RLock()
|
||
defer pm.mu.RUnlock()
|
||
|
||
results := make(map[string]interface{})
|
||
|
||
if typePlugins, exists := pm.pluginsByType[pluginType]; exists {
|
||
for name, plugin := range typePlugins {
|
||
if !plugin.IsEnabled() {
|
||
continue
|
||
}
|
||
|
||
result, err := plugin.Execute(ctx, action, params)
|
||
results[name] = map[string]interface{}{
|
||
"result": result,
|
||
"error": err,
|
||
}
|
||
}
|
||
}
|
||
|
||
return results
|
||
}
|
||
|
||
// ExecuteAllPlugins 对所有插件执行操作
|
||
func (pm *PluginManager) ExecuteAllPlugins(ctx context.Context, action string, params map[string]interface{}) map[string]interface{} {
|
||
pm.mu.RLock()
|
||
defer pm.mu.RUnlock()
|
||
|
||
results := make(map[string]interface{})
|
||
|
||
for name, plugin := range pm.plugins {
|
||
if !plugin.IsEnabled() {
|
||
continue
|
||
}
|
||
|
||
result, err := plugin.Execute(ctx, action, params)
|
||
results[name] = map[string]interface{}{
|
||
"result": result,
|
||
"error": err,
|
||
}
|
||
}
|
||
|
||
return results
|
||
}
|
||
|
||
// GetPluginOperationInfo 获取插件特定操作的参数信息
|
||
func (pm *PluginManager) GetPluginOperationInfo(name string, operation string) (map[string]interface{}, error) {
|
||
pm.mu.RLock()
|
||
defer pm.mu.RUnlock()
|
||
|
||
plugin, exists := pm.plugins[name]
|
||
if !exists {
|
||
return nil, fmt.Errorf("插件 %s 不存在", name)
|
||
}
|
||
|
||
if !plugin.IsEnabled() {
|
||
return nil, fmt.Errorf("插件 %s 已禁用", name)
|
||
}
|
||
|
||
return plugin.GetOperationInfo(operation)
|
||
}
|
||
|
||
// GetPluginAllOperations 获取插件所有操作及其参数信息
|
||
func (pm *PluginManager) GetPluginAllOperations(name string) (map[string]map[string]interface{}, error) {
|
||
pm.mu.RLock()
|
||
defer pm.mu.RUnlock()
|
||
|
||
plugin, exists := pm.plugins[name]
|
||
if !exists {
|
||
return nil, fmt.Errorf("插件 %s 不存在", name)
|
||
}
|
||
|
||
if !plugin.IsEnabled() {
|
||
return nil, fmt.Errorf("插件 %s 已禁用", name)
|
||
}
|
||
|
||
return plugin.GetAllOperations(), nil
|
||
}
|
||
|
||
// GetOperationsByType 获取指定类型插件的所有操作信息
|
||
func (pm *PluginManager) GetOperationsByType(pluginType PluginType) map[string]map[string]map[string]interface{} {
|
||
pm.mu.RLock()
|
||
defer pm.mu.RUnlock()
|
||
|
||
result := make(map[string]map[string]map[string]interface{})
|
||
|
||
if typePlugins, exists := pm.pluginsByType[pluginType]; exists {
|
||
for name, plugin := range typePlugins {
|
||
if !plugin.IsEnabled() {
|
||
continue
|
||
}
|
||
|
||
result[name] = plugin.GetAllOperations()
|
||
}
|
||
}
|
||
|
||
return result
|
||
}
|
||
|
||
// GetAllPluginsOperations 获取所有插件的所有操作信息
|
||
func (pm *PluginManager) GetAllPluginsOperations() map[string]map[string]map[string]interface{} {
|
||
pm.mu.RLock()
|
||
defer pm.mu.RUnlock()
|
||
|
||
result := make(map[string]map[string]map[string]interface{})
|
||
|
||
for name, plugin := range pm.plugins {
|
||
if !plugin.IsEnabled() {
|
||
continue
|
||
}
|
||
|
||
result[name] = plugin.GetAllOperations()
|
||
}
|
||
|
||
return result
|
||
} |