Skip to main content

oxidite_plugin/
manager.rs

1use std::collections::HashMap;
2use std::path::Path;
3use std::sync::Arc;
4use serde::{Deserialize, Serialize};
5use oxidite_core::{Result, Error};
6
7use crate::{Plugin, PluginInfo, PluginHook, HookResult, PluginLoader, PluginConfig};
8
9/// Main plugin manager
10pub struct PluginManager {
11    plugins: HashMap<String, Arc<dyn Plugin>>,
12    config: PluginConfig,
13    hooks: HashMap<String, Vec<Arc<dyn Plugin>>>,
14}
15
16impl PluginManager {
17    pub fn new(config: PluginConfig) -> Self {
18        Self {
19            plugins: HashMap::new(),
20            config,
21            hooks: HashMap::new(),
22        }
23    }
24    
25    /// Load plugins from a directory
26    pub async fn load_plugins_from_directory<P: AsRef<Path>>(&mut self, path: P) -> Result<()> {
27        let loader = PluginLoader::new();
28        
29        // For now, we'll just simulate loading
30        // In a real implementation, this would dynamically load .so/.dll files
31        println!("Loading plugins from: {:?}", path.as_ref());
32        
33        Ok(())
34    }
35    
36    /// Register a plugin
37    pub fn register_plugin(&mut self, plugin: Arc<dyn Plugin>) -> Result<()> {
38        let info = plugin.info();
39        
40        if self.plugins.contains_key(&info.id) {
41            return Err(Error::InternalServerError(
42                format!("Plugin with id '{}' already exists", info.id)
43            ));
44        }
45        
46        self.plugins.insert(info.id.clone(), plugin);
47        
48        Ok(())
49    }
50    
51    /// Enable a plugin
52    pub async fn enable_plugin(&mut self, plugin_id: &str) -> Result<()> {
53        if let Some(plugin) = self.plugins.get(plugin_id) {
54            plugin.on_enable().await?;
55            
56            // Update plugin info to enabled
57            // Note: In a real implementation, we'd need mutable access to update the info
58            
59            Ok(())
60        } else {
61            Err(Error::NotFound(format!("Plugin '{}' not found", plugin_id)))
62        }
63    }
64    
65    /// Disable a plugin
66    pub async fn disable_plugin(&mut self, plugin_id: &str) -> Result<()> {
67        if let Some(plugin) = self.plugins.get(plugin_id) {
68            plugin.on_disable().await?;
69            Ok(())
70        } else {
71            Err(Error::NotFound(format!("Plugin '{}' not found", plugin_id)))
72        }
73    }
74    
75    /// Execute a hook across all registered plugins
76    pub async fn execute_hook(&self, hook: PluginHook) -> Result<HookResult> {
77        let mut result = HookResult::Continue;
78        
79        for plugin in self.plugins.values() {
80            if !plugin.info().enabled {
81                continue;
82            }
83            
84            result = plugin.hook(hook.clone()).await;
85            
86            match result {
87                HookResult::Stop => break,
88                HookResult::Response(_) => return Ok(result),
89                HookResult::Error(_) => return Ok(result),
90                _ => continue,
91            }
92        }
93        
94        Ok(result)
95    }
96    
97    /// Get a list of all plugins
98    pub fn list_plugins(&self) -> Vec<PluginInfo> {
99        self.plugins.values()
100            .map(|p| p.info())
101            .collect()
102    }
103    
104    /// Initialize all enabled plugins
105    pub async fn initialize(&self) -> Result<()> {
106        for plugin in self.plugins.values() {
107            if plugin.info().enabled {
108                plugin.on_load().await?;
109            }
110        }
111        
112        Ok(())
113    }
114    
115    /// Shutdown all plugins
116    pub async fn shutdown(&self) -> Result<()> {
117        for plugin in self.plugins.values() {
118            plugin.on_unload().await?;
119        }
120        
121        Ok(())
122    }
123}
124
125/// Helper function to create a plugin manager
126pub fn create_manager(config: PluginConfig) -> PluginManager {
127    PluginManager::new(config)
128}
129