1use crate::core::{RuntimeContext, Result};
2use std::collections::{HashMap, HashSet};
3
4pub trait EnterprisePlugin: Send + Sync {
7 fn name(&self) -> &str;
9
10 fn initialize(&mut self, context: &mut RuntimeContext) -> Result<()>;
12
13 fn features(&self) -> Vec<String>;
15
16 fn shutdown(&mut self) -> Result<()>;
18
19 fn version(&self) -> &str {
21 "1.0.0"
22 }
23
24 fn is_compatible(&self, runtime_version: &str) -> bool {
26 runtime_version.starts_with("0.1") || runtime_version.starts_with("1.")
28 }
29}
30
31pub struct PluginManager {
33 plugins: HashMap<String, Box<dyn EnterprisePlugin>>,
34 enabled_features: HashSet<String>,
35 runtime_version: String,
36}
37
38impl PluginManager {
39 pub fn new() -> Self {
40 Self {
41 plugins: HashMap::new(),
42 enabled_features: HashSet::new(),
43 runtime_version: "0.1.0".to_string(),
44 }
45 }
46
47 pub fn register(&mut self, plugin: Box<dyn EnterprisePlugin>) -> Result<()> {
49 let name = plugin.name().to_string();
50
51 if !plugin.is_compatible(&self.runtime_version) {
53 return Err(crate::core::error::RustChainError::Config(
54 crate::core::error::ConfigError::PluginError {
55 message: format!("Plugin {} is not compatible with runtime version {}",
56 name, self.runtime_version)
57 }
58 ));
59 }
60
61 let features = plugin.features();
63 for feature in features {
64 self.enabled_features.insert(feature);
65 }
66
67 self.plugins.insert(name, plugin);
68 Ok(())
69 }
70
71 pub fn initialize_all(&mut self, context: &mut RuntimeContext) -> Result<()> {
73 for (name, plugin) in self.plugins.iter_mut() {
74 plugin.initialize(context)
75 .map_err(|e| crate::core::error::RustChainError::Config(
76 crate::core::error::ConfigError::PluginError {
77 message: format!("Failed to initialize plugin {}: {}", name, e)
78 }
79 ))?;
80 }
81 Ok(())
82 }
83
84 pub fn has_feature(&self, feature: &str) -> bool {
86 self.enabled_features.contains(feature)
87 }
88
89 pub fn enabled_features(&self) -> Vec<String> {
91 self.enabled_features.iter().cloned().collect()
92 }
93
94 pub fn loaded_plugins(&self) -> Vec<String> {
96 self.plugins.keys().cloned().collect()
97 }
98
99 pub fn shutdown_all(&mut self) -> Result<()> {
101 let mut errors = Vec::new();
102
103 for (name, plugin) in self.plugins.iter_mut() {
104 if let Err(e) = plugin.shutdown() {
105 errors.push(format!("Plugin {} shutdown error: {}", name, e));
106 }
107 }
108
109 if !errors.is_empty() {
110 return Err(crate::core::error::RustChainError::Config(
111 crate::core::error::ConfigError::PluginError {
112 message: format!("Plugin shutdown errors: {}", errors.join("; "))
113 }
114 ));
115 }
116
117 self.plugins.clear();
118 self.enabled_features.clear();
119 Ok(())
120 }
121}
122
123impl Default for PluginManager {
124 fn default() -> Self {
125 Self::new()
126 }
127}
128
129#[cfg(test)]
130mod tests {
131 use super::*;
132 use crate::core::RuntimeContext;
133
134 struct MockPlugin {
135 name: String,
136 features: Vec<String>,
137 initialized: bool,
138 }
139
140 impl MockPlugin {
141 fn new(name: &str, features: Vec<&str>) -> Self {
142 Self {
143 name: name.to_string(),
144 features: features.into_iter().map(|s| s.to_string()).collect(),
145 initialized: false,
146 }
147 }
148 }
149
150 impl EnterprisePlugin for MockPlugin {
151 fn name(&self) -> &str {
152 &self.name
153 }
154
155 fn initialize(&mut self, _context: &mut RuntimeContext) -> Result<()> {
156 self.initialized = true;
157 Ok(())
158 }
159
160 fn features(&self) -> Vec<String> {
161 self.features.clone()
162 }
163
164 fn shutdown(&mut self) -> Result<()> {
165 self.initialized = false;
166 Ok(())
167 }
168 }
169
170 #[test]
171 fn test_plugin_manager_creation() {
172 let manager = PluginManager::new();
173 assert_eq!(manager.loaded_plugins().len(), 0);
174 assert_eq!(manager.enabled_features().len(), 0);
175 }
176
177 #[test]
178 fn test_plugin_registration() {
179 let mut manager = PluginManager::new();
180 let plugin = Box::new(MockPlugin::new("test", vec!["feature1", "feature2"]));
181
182 assert!(manager.register(plugin).is_ok());
183 assert_eq!(manager.loaded_plugins().len(), 1);
184 assert_eq!(manager.enabled_features().len(), 2);
185 assert!(manager.has_feature("feature1"));
186 assert!(manager.has_feature("feature2"));
187 assert!(!manager.has_feature("feature3"));
188 }
189
190 #[test]
191 fn test_plugin_initialization() {
192 let mut manager = PluginManager::new();
193 let plugin = Box::new(MockPlugin::new("test", vec!["feature1"]));
194
195 manager.register(plugin).unwrap();
196
197 let mut context = RuntimeContext::new();
198 assert!(manager.initialize_all(&mut context).is_ok());
199 }
200
201 #[test]
202 fn test_plugin_shutdown() {
203 let mut manager = PluginManager::new();
204 let plugin = Box::new(MockPlugin::new("test", vec!["feature1"]));
205
206 manager.register(plugin).unwrap();
207 assert_eq!(manager.loaded_plugins().len(), 1);
208
209 assert!(manager.shutdown_all().is_ok());
210 assert_eq!(manager.loaded_plugins().len(), 0);
211 assert_eq!(manager.enabled_features().len(), 0);
212 }
213}