source: trunk/Packages/ModularSystem/ModularSystem.pas

Last change on this file was 150, checked in by chronos, 9 months ago
  • Modified: ModularSystem renamed to not have U prefix in unit name.
File size: 12.7 KB
Line 
1unit ModularSystem;
2
3interface
4
5uses
6 Classes, SysUtils, Generics.Collections, RegistryEx;
7
8type
9 TModuleManager = class;
10
11 TAPI = class(TComponent)
12 end;
13
14 { TModule }
15
16 TModule = class(TComponent)
17 private
18 FEnabled: Boolean;
19 FRunning: Boolean;
20 FInstalled: Boolean;
21 FManager: TModuleManager;
22 FVersion: string;
23 FIdentification: string;
24 FTitle: string;
25 FLicense: string;
26 FAuthor: string;
27 FDependencies: TStringList;
28 FDescription: TStringList;
29 procedure SetEnabled(AValue: Boolean);
30 procedure SetInstalled(AValue: Boolean);
31 procedure SetRunning(AValue: Boolean);
32 protected
33 procedure BeforeStart; virtual;
34 procedure AfterStart; virtual;
35 procedure BeforeStop; virtual;
36 procedure AfterStop; virtual;
37 public
38 API: TAPI;
39 procedure Start; virtual;
40 procedure Stop; virtual;
41 procedure Install; virtual;
42 procedure Uninstall; virtual;
43 procedure Upgrade; virtual;
44 procedure EnumModulesStart(ModuleList: TStringList);
45 procedure EnumModulesStop(ModuleList: TStringList);
46 procedure EnumModulesInstall(ModuleList: TStringList);
47 procedure EnumModulesUninstall(ModuleList: TStringList);
48 procedure SetInstalledState(Value: Boolean);
49 constructor Create(Owner: TComponent); override;
50 destructor Destroy; override;
51 property Running: Boolean read FRunning write SetRunning;
52 property Installed: Boolean read FInstalled write SetInstalled;
53 property Enabled: Boolean read FEnabled write SetEnabled;
54 published
55 property Manager: TModuleManager read FManager;
56 property Version: string read FVersion write FVersion;
57 property Identification: string read FIdentification write FIdentification;
58 property Title: string read FTitle write FTitle;
59 property License: string read FLicense write FLicense;
60 property Author: string read FAuthor write FAuthor;
61 property Dependencies: TStringList read FDependencies write FDependencies;
62 property Description: TStringList read FDescription write FDescription;
63 end;
64
65 TModules = class(TObjectList<TModule>)
66 end;
67
68 TModuleEvent = procedure (Sender: TObject; Module: TModule) of object;
69
70 { TModuleManager }
71
72 TModuleManager = class(TComponent)
73 private
74 FAPI: TAPI;
75 FOnModuleChange: TModuleEvent;
76 procedure SetAPI(AValue: TAPI);
77 public
78 Modules: TModules;
79 function FindModuleByName(Name: string): TModule;
80 function ModuleRunning(Name: string): Boolean;
81 procedure StartDependencies(ModuleName: string; Dependencies: TStringList);
82 procedure StopDependencies(ModuleName: string);
83 procedure EnumModulesStart(Dependencies, ModuleList: TStringList);
84 procedure EnumModulesStop(ModuleName: string; ModuleList: TStringList);
85 procedure InstallDependencies(ModuleName: string; Dependencies: TStringList);
86 procedure UninstallDependencies(ModuleName: string);
87 procedure EnumModulesInstall(Dependencies, ModuleList: TStringList);
88 procedure EnumModulesUninstall(ModuleName: string; ModuleList: TStringList);
89 procedure RegisterModule(Module: TModule; Enabled: Boolean = True);
90 procedure UnregisterModule(Module: TModule);
91 procedure StartInstalled;
92 procedure InstallEnabled;
93 procedure StopAll;
94 procedure UninstallAll;
95 procedure LoadFromRegistry(Context: TRegistryContext);
96 procedure SaveToRegistry(Context: TRegistryContext);
97 constructor Create(AOwner: TComponent); override;
98 destructor Destroy; override;
99 property API: TAPI read FAPI write SetAPI;
100 property OnModuleChange: TModuleEvent read FOnModuleChange write FOnModuleChange;
101 end;
102
103procedure Register;
104
105
106implementation
107
108resourcestring
109 SModuleNotFound = 'Module "%1:s" not found as dependency for module "%0:s"';
110
111procedure Register;
112begin
113 RegisterComponents('ModularSystem', [TModuleManager, TModule]);
114end;
115
116{ TModuleManager }
117
118procedure TModuleManager.SetAPI(AValue: TAPI);
119var
120 I: Integer;
121begin
122 if FAPI = AValue then Exit;
123 FAPI := AValue;
124 for I := 0 to Modules.Count - 1 do
125 TModule(Modules[I]).API := FAPI;
126end;
127
128function TModuleManager.FindModuleByName(Name: string): TModule;
129var
130 I: Integer;
131begin
132 I := 0;
133 while (I < Modules.Count) and (Modules[I].Identification <> Name) do Inc(I);
134 if I < Modules.Count then Result := Modules[I]
135 else Result := nil;
136end;
137
138function TModuleManager.ModuleRunning(Name: string): Boolean;
139var
140 Module: TModule;
141begin
142 Module := FindModuleByName(Name);
143 if Assigned(Module) then begin
144 Result := Module.Running;
145 end else Result := False;
146end;
147
148procedure TModuleManager.StartDependencies(ModuleName: string; Dependencies: TStringList);
149var
150 Module: TModule;
151 I: Integer;
152begin
153 for I := 0 to Dependencies.Count - 1 do begin
154 Module := FindModuleByName(Dependencies[I]);
155 if Assigned(Module) and Module.Enabled then begin
156 if not Module.Running then Module.Start;
157 end else raise Exception.CreateFmt(SModuleNotFound, [ModuleName, Dependencies[I]]);
158 end;
159end;
160
161procedure TModuleManager.StopDependencies(ModuleName: string);
162var
163 I: Integer;
164begin
165 for I := 0 to Modules.Count - 1 do
166 with TModule(Modules[I]) do begin
167 if (Dependencies.IndexOf(ModuleName) <> - 1) and Running then Stop;
168 end;
169end;
170
171procedure TModuleManager.EnumModulesStart(Dependencies,
172 ModuleList: TStringList);
173var
174 Module: TModule;
175 I: Integer;
176begin
177 for I := 0 to Dependencies.Count - 1 do begin
178 Module := FindModuleByName(Dependencies[I]);
179 if Assigned(Module) then begin
180 if not Module.Running and (ModuleList.IndexOf(Module.Identification) = -1) then begin
181 ModuleList.Add(Module.Identification);
182 EnumModulesStart(Module.Dependencies, ModuleList);
183 end;
184 end else raise Exception.CreateFmt(SModuleNotFound, [Module.Identification]);
185 end;
186end;
187
188procedure TModuleManager.EnumModulesStop(ModuleName: string;
189 ModuleList: TStringList);
190var
191 I: Integer;
192begin
193 for I := 0 to Modules.Count - 1 do
194 with TModule(Modules[I]) do begin
195 if (Dependencies.IndexOf(ModuleName) <> -1) and Running and
196 (ModuleList.IndexOf(Identification) = -1) then begin
197 ModuleList.Add(Identification);
198 Self.EnumModulesStop(Identification, ModuleList);
199 end;
200 end;
201end;
202
203procedure TModuleManager.InstallDependencies(ModuleName: string;
204 Dependencies: TStringList);
205var
206 Module: TModule;
207 I: Integer;
208begin
209 for I := 0 to Dependencies.Count - 1 do begin
210 Module := FindModuleByName(Dependencies[I]);
211 if Assigned(Module) and Module.Enabled then begin
212 if not Module.Installed then Module.Install;
213 end else raise Exception.CreateFmt(SModuleNotFound, [ModuleName, Dependencies[I]]);
214 end;
215end;
216
217procedure TModuleManager.UninstallDependencies(ModuleName: string);
218var
219 I: Integer;
220begin
221 for I := 0 to Modules.Count - 1 do
222 with TModule(Modules[I]) do begin
223 if (Dependencies.IndexOf(ModuleName) <> - 1) and Installed then Uninstall;
224 end;
225end;
226
227procedure TModuleManager.EnumModulesInstall(Dependencies,
228 ModuleList: TStringList);
229var
230 Module: TModule;
231 I: Integer;
232begin
233 for I := 0 to Dependencies.Count - 1 do begin
234 Module := FindModuleByName(Dependencies[I]);
235 if Assigned(Module) then begin
236 if not Module.Installed and (ModuleList.IndexOf(Module.Identification) = -1) then begin
237 ModuleList.Add(Module.Identification);
238 EnumModulesInstall(Module.Dependencies, ModuleList);
239 end;
240 end else raise Exception.CreateFmt(SModuleNotFound, [Module.Identification]);
241 end;
242end;
243
244procedure TModuleManager.EnumModulesUninstall(ModuleName: string;
245 ModuleList: TStringList);
246var
247 I: Integer;
248begin
249 for I := 0 to Modules.Count - 1 do
250 with TModule(Modules[I]) do begin
251 if (Dependencies.IndexOf(ModuleName) <> -1) and Installed and
252 (ModuleList.IndexOf(Identification) = -1) then begin
253 ModuleList.Add(Identification);
254 Self.EnumModulesUninstall(Identification, ModuleList);
255 end;
256 end;
257end;
258
259procedure TModuleManager.RegisterModule(Module: TModule;
260 Enabled: Boolean = True);
261begin
262 Modules.Add(Module);
263 Module.FManager := Self;
264 Module.API := API;
265 Module.Enabled := Enabled;
266end;
267
268procedure TModuleManager.UnregisterModule(Module: TModule);
269begin
270 Modules.Remove(Module);
271end;
272
273procedure TModuleManager.StartInstalled;
274var
275 I: Integer;
276begin
277 for I := 0 to Modules.Count - 1 do
278 with TModule(Modules[I]) do
279 if not Running and Installed then Start;
280end;
281
282procedure TModuleManager.InstallEnabled;
283var
284 I: Integer;
285begin
286 for I := 0 to Modules.Count - 1 do
287 with TModule(Modules[I]) do
288 if not Installed and Enabled then Install;
289end;
290
291procedure TModuleManager.StopAll;
292var
293 I: Integer;
294begin
295 for I := 0 to Modules.Count - 1 do
296 with TModule(Modules[I]) do
297 if Running then Stop;
298end;
299
300procedure TModuleManager.UninstallAll;
301var
302 I: Integer;
303begin
304 for I := 0 to Modules.Count - 1 do
305 with TModule(Modules[I]) do
306 if Installed then Uninstall;
307end;
308
309constructor TModuleManager.Create(AOwner: TComponent);
310begin
311 inherited;
312 Modules := TModules.Create;
313 //Modules.OwnsObjects := False;
314end;
315
316destructor TModuleManager.Destroy;
317begin
318 StopAll;
319 FreeAndNil(Modules);
320 inherited;
321end;
322
323procedure TModuleManager.LoadFromRegistry(Context: TRegistryContext);
324var
325 I: Integer;
326begin
327 with TRegistryEx.Create do
328 try
329 RootKey := Context.RootKey;
330 for I := 0 to Modules.Count - 1 do
331 with TModule(Modules[I]) do begin
332 OpenKey(Context.Key + '\' + Identification, True);
333 Running := ReadBoolWithDefault('Run', Enabled);
334 end;
335 finally
336 Free;
337 end;
338end;
339
340procedure TModuleManager.SaveToRegistry(Context: TRegistryContext);
341var
342 I: Integer;
343begin
344 with TRegistryEx.Create do
345 try
346 RootKey := Context.RootKey;
347 for I := 0 to Modules.Count - 1 do
348 with TModule(Modules[I]) do begin
349 OpenKey(Context.Key + '\' + Identification, True);
350 WriteBool('Run', Running);
351 end;
352 finally
353 Free;
354 end;
355end;
356
357{ TModule }
358
359procedure TModule.SetRunning(AValue: Boolean);
360begin
361 if FRunning = AValue then Exit;
362 if AValue then Start else Stop;
363end;
364
365procedure TModule.BeforeStart;
366begin
367 if Running then Exit;
368 if not Installed then Install;
369 Manager.StartDependencies(Identification, Dependencies);
370end;
371
372procedure TModule.AfterStart;
373begin
374 FRunning := True;
375end;
376
377procedure TModule.BeforeStop;
378begin
379 if not Running then Exit;
380 FRunning := False;
381 Manager.StopDependencies(Identification);
382end;
383
384procedure TModule.AfterStop;
385begin
386end;
387
388procedure TModule.SetInstalled(AValue: Boolean);
389begin
390 if FInstalled = AValue then Exit;
391 if AValue then Install else Uninstall;
392end;
393
394procedure TModule.SetEnabled(AValue: Boolean);
395begin
396 if FEnabled = AValue then Exit;
397 FEnabled := AValue;
398 if not FEnabled and FInstalled then Uninstall;
399end;
400
401procedure TModule.Start;
402begin
403 BeforeStart;
404 // Do something
405 AfterStart;
406end;
407
408procedure TModule.Stop;
409begin
410 BeforeStop;
411 // Do something
412 AfterStop;
413end;
414
415procedure TModule.Install;
416begin
417 if Installed then Exit;
418 Manager.InstallDependencies(Identification, Dependencies);
419 FInstalled := True;
420 if Assigned(Manager.FOnModuleChange) then
421 Manager.FOnModuleChange(Manager, Self);
422end;
423
424procedure TModule.Uninstall;
425begin
426 if not Installed then Exit;
427 if Running then Stop;
428 Manager.UninstallDependencies(Identification);
429 FInstalled := False;
430 if Assigned(Manager.FOnModuleChange) then
431 Manager.FOnModuleChange(Manager, Self);
432end;
433
434procedure TModule.Upgrade;
435begin
436 if not Running then Exit;
437end;
438
439procedure TModule.EnumModulesStart(ModuleList: TStringList);
440begin
441 ModuleList.Clear;
442 Manager.EnumModulesStart(Dependencies, ModuleList);
443end;
444
445procedure TModule.EnumModulesStop(ModuleList: TStringList);
446begin
447 ModuleList.Clear;
448 Manager.EnumModulesStop(Identification, ModuleList);
449end;
450
451procedure TModule.EnumModulesInstall(ModuleList: TStringList);
452begin
453 ModuleList.Clear;
454 Manager.EnumModulesInstall(Dependencies, ModuleList);
455end;
456
457procedure TModule.EnumModulesUninstall(ModuleList: TStringList);
458begin
459 ModuleList.Clear;
460 Manager.EnumModulesUninstall(Identification, ModuleList);
461end;
462
463procedure TModule.SetInstalledState(Value: Boolean);
464begin
465 FInstalled := Value;
466 if Assigned(Manager.FOnModuleChange) then
467 Manager.FOnModuleChange(Manager, Self);
468end;
469
470constructor TModule.Create(Owner: TComponent);
471begin
472 inherited;
473 Dependencies := TStringList.Create;
474 Description := TStringList.Create;
475end;
476
477destructor TModule.Destroy;
478begin
479 Running := False;
480 FreeAndNil(FDescription);
481 FreeAndNil(FDependencies);
482 inherited;
483end;
484
485end.
486
Note: See TracBrowser for help on using the repository browser.