Changeset 431 for ModularSystem/UModularSystem.pas
- Timestamp:
- Oct 25, 2012, 2:11:02 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
ModularSystem/UModularSystem.pas
r429 r431 6 6 7 7 uses 8 Classes, SysUtils, Contnrs, URegistry;8 Classes, SysUtils, URegistry, SpecializedList; 9 9 10 10 type 11 11 TModuleManager = class; 12 TModule = class; 13 TListModule = class; 12 14 13 15 TAPI = class(TComponent) 14 16 15 17 end; 18 19 TModuleCondition = (mcAll, mcEnabled, mcNotEnabled, mcInstalled, mcNotInstalled, 20 mcRunning, mcNotRunning); 21 TModuleConditions = set of TModuleCondition; 22 TModuleAction = (maStart, maStop, maInstall, maUninstall, maUpgrade, maEnable, 23 maDisable); 24 TModuleActions = array of TModuleAction; 16 25 17 26 { TModule } … … 19 28 TModule = class(TComponent) 20 29 private 30 FCategory: string; 21 31 FEnabled: Boolean; 32 FReleaseTime: TDateTime; 22 33 FRunning: Boolean; 23 34 FInstalled: Boolean; … … 28 39 FLicense: string; 29 40 FAuthor: string; 30 FDependencies: TStringList; 31 FDescription: TStringList; 41 FDependencies: TListString; 42 FDescription: TListString; 43 FFileName: string; 44 FWebSite: string; 32 45 procedure SetEnabled(AValue: Boolean); 33 46 procedure SetInstalled(AValue: Boolean); 47 procedure SetManager(AValue: TModuleManager); 34 48 procedure SetRunning(AValue: Boolean); 35 49 protected … … 41 55 public 42 56 API: TAPI; 57 procedure Enable; 58 procedure Disable; 43 59 procedure Start; 44 60 procedure Stop; 61 procedure Restart; 45 62 procedure Install; 46 63 procedure Uninstall; 64 procedure Reinstall; 47 65 procedure Upgrade; 48 procedure Enum ModulesStart(ModuleList: TStringList);49 procedure EnumModulesStop(ModuleList: TStringList);50 procedure Enum ModulesInstall(ModuleList: TStringList);51 procedure EnumModulesUninstall(ModuleList: TStringList);66 procedure EnumDependenciesCascade(ModuleList: TListModule; 67 Conditions: TModuleConditions = [mcAll]); 68 procedure EnumSuperiorDependenciesCascade(ModuleList: TListModule; 69 Conditions: TModuleConditions = [mcAll]); 52 70 procedure SetInstalledState(Value: Boolean); 53 71 constructor Create(Owner: TComponent); override; … … 57 75 property Enabled: Boolean read FEnabled write SetEnabled; 58 76 published 59 property Manager: TModuleManager read FManager; 77 property Identification: string read FIdentification write FIdentification; // Unique system name 78 property Manager: TModuleManager read FManager write SetManager; 60 79 property Version: string read FVersion write FVersion; 61 property Identification: string read FIdentification write FIdentification;80 property ReleaseTime: TDateTime read FReleaseTime write FReleaseTime; 62 81 property Title: string read FTitle write FTitle; 63 82 property License: string read FLicense write FLicense; 64 83 property Author: string read FAuthor write FAuthor; 65 property Dependencies: TStringList read FDependencies write FDependencies; 66 property Description: TStringList read FDescription write FDescription; 67 end; 68 69 TModuleEvent = procedure (Sender: TObject; Module: TModule) of object; 70 84 property Dependencies: TListString read FDependencies write FDependencies; 85 property Description: TListString read FDescription write FDescription; 86 property FileName: string read FFileName write FFileName; 87 property Category: string read FCategory write FCategory; 88 property WebSite: string read FWebSite write FWebSite; 89 // Screenshots, reviews, icon, weak dependencies, ... 90 end; 91 92 { TListModule } 93 94 TListModule = class(TListObject) 95 private 96 public 97 procedure Perform(Actions: array of TModuleAction; Conditions: TModuleConditions = [mcAll]); 98 function FindByName(Name: string): TModule; 99 end; 100 101 TModuleManagerOption = (moAutoInstallOnRun, moAuto); 102 TModuleManagerOptions = set of TModuleManagerOption; 71 103 { TModuleManager } 72 104 … … 74 106 private 75 107 FAPI: TAPI; 76 FOnModuleChange: TModuleEvent; 108 FOnUpdate: TNotifyEvent; 109 FUpdateCount: Integer; 110 FOptions: TModuleManagerOptions; 77 111 procedure SetAPI(AValue: TAPI); 112 procedure DoUpdate; 78 113 public 79 Modules: TObjectList; // TObjectList<TModule> 80 function FindModuleByName(Name: string): TModule; 114 Modules: TListModule; // TObjectList<TModule> 81 115 function ModuleRunning(Name: string): Boolean; 82 procedure StartDependencies(ModuleName: string; Dependencies: TStringList); 83 procedure StopDependencies(ModuleName: string); 84 procedure EnumModulesStart(Dependencies, ModuleList: TStringList); 85 procedure EnumModulesStop(ModuleName: string; ModuleList: TStringList); 86 procedure InstallDependencies(ModuleName: string; Dependencies: TStringList); 87 procedure UninstallDependencies(ModuleName: string); 88 procedure EnumModulesInstall(Dependencies, ModuleList: TStringList); 89 procedure EnumModulesUninstall(ModuleName: string; ModuleList: TStringList); 90 procedure RegisterModule(Module: TModule; Enabled: Boolean = True); 116 procedure EnumDependenciesCascade(Module: TModule; ModuleList: TListModule; 117 Conditions: TModuleConditions = [mcAll]); 118 procedure EnumSuperiorDependenciesCascade(Module: TModule; 119 ModuleList: TListModule; Conditions: TModuleConditions = [mcAll]); 120 procedure RegisterModule(Module: TModule); 91 121 procedure UnregisterModule(Module: TModule); 92 procedure StartInstalled;93 procedure InstallEnabled;94 procedure StopAll;95 procedure UninstallAll;96 122 procedure LoadFromRegistry(Context: TRegistryContext); 97 123 procedure SaveToRegistry(Context: TRegistryContext); 124 procedure BeginUpdate; 125 procedure EndUpdate; 126 procedure Update; 98 127 constructor Create(AOwner: TComponent); override; 99 128 destructor Destroy; override; 100 129 property API: TAPI read FAPI write SetAPI; 101 property OnModuleChange: TModuleEvent read FOnModuleChange write FOnModuleChange; 130 published 131 property OnUpdate: TNotifyEvent read FOnUpdate write FOnUpdate; 132 property Options: TModuleManagerOptions read FOptions write FOptions; 102 133 end; 103 134 … … 113 144 begin 114 145 RegisterComponents('ModularSystem', [TModuleManager, TModule]); 146 end; 147 148 { TListModule } 149 150 procedure TListModule.Perform(Actions: array of TModuleAction; 151 Conditions: TModuleConditions = [mcAll]); 152 var 153 I: Integer; 154 A: Integer; 155 begin 156 for I := 0 to Count - 1 do 157 with TModule(Items[I]) do 158 if (mcAll in Conditions) or 159 (Running and (mcRunning in Conditions)) or 160 (not Running and (mcNotRunning in Conditions)) or 161 (Installed and (mcInstalled in Conditions)) or 162 (not Installed and (mcNotInstalled in Conditions)) or 163 (Enabled and (mcEnabled in Conditions)) or 164 (not Enabled and (mcNotEnabled in Conditions)) then 165 for A := 0 to High(Actions) do begin 166 if Actions[A] = maStart then Start; 167 if Actions[A] = maStop then Stop; 168 if Actions[A] = maInstall then Install; 169 if Actions[A] = maUninstall then Uninstall; 170 if Actions[A] = maUpgrade then Upgrade; 171 if Actions[A] = maEnable then Enabled := True; 172 if Actions[A] = maDisable then Enabled := False; 173 end; 174 end; 175 176 function TListModule.FindByName(Name: string): TModule; 177 var 178 I: Integer; 179 begin 180 I := 0; 181 while (I < Count) and (TModule(Items[I]).Identification <> Name) do Inc(I); 182 if I < Count then Result := TModule(Items[I]) 183 else Result := nil; 115 184 end; 116 185 … … 127 196 end; 128 197 129 function TModuleManager.FindModuleByName(Name: string): TModule; 130 var 131 I: Integer; 132 begin 133 I := 0; 134 while (I < Modules.Count) and (TModule(Modules[I]).Identification <> Name) do Inc(I); 135 if I < Modules.Count then Result := TModule(Modules[I]) 136 else Result := nil; 198 procedure TModuleManager.DoUpdate; 199 begin 200 if Assigned(FOnUpdate) then FOnUpdate(Self); 137 201 end; 138 202 … … 141 205 Module: TModule; 142 206 begin 143 Module := FindModuleByName(Name);207 Module := Modules.FindByName(Name); 144 208 if Assigned(Module) then begin 145 209 Result := Module.Running; … … 147 211 end; 148 212 149 procedure TModuleManager.StartDependencies(ModuleName: string; Dependencies: TStringList); 150 var 151 Module: TModule; 152 I: Integer; 153 begin 154 for I := 0 to Dependencies.Count - 1 do begin 155 Module := FindModuleByName(Dependencies[I]); 156 if Assigned(Module) and Module.Enabled then begin 157 if not Module.Running then Module.Start; 158 end else raise Exception.CreateFmt(SModuleNotFound, [ModuleName, Dependencies[I]]); 159 end; 160 end; 161 162 procedure TModuleManager.StopDependencies(ModuleName: string); 213 procedure TModuleManager.EnumDependenciesCascade(Module: TModule; 214 ModuleList: TListModule; Conditions: TModuleConditions = [mcAll]); 215 var 216 DepModule: TModule; 217 I: Integer; 218 begin 219 for I := 0 to Module.Dependencies.Count - 1 do begin 220 DepModule := Modules.FindByName(Module.Dependencies[I]); 221 if Assigned(DepModule) then 222 with DepModule do begin 223 if (ModuleList.IndexOf(DepModule) = -1) and 224 ((mcAll in Conditions) or 225 (Running and (mcRunning in Conditions)) or 226 (not Running and (mcNotRunning in Conditions)) or 227 (Installed and (mcInstalled in Conditions)) or 228 (not Installed and (mcNotInstalled in Conditions)) or 229 (Enabled and (mcEnabled in Conditions)) or 230 (not Enabled and (mcNotEnabled in Conditions))) then begin 231 ModuleList.Add(DepModule); 232 Self.EnumDependenciesCascade(DepModule, ModuleList); 233 end; 234 end else raise Exception.CreateFmt(SModuleNotFound, [DepModule.Identification]); 235 end; 236 end; 237 238 procedure TModuleManager.EnumSuperiorDependenciesCascade(Module: TModule; 239 ModuleList: TListModule; Conditions: TModuleConditions = [mcAll]); 163 240 var 164 241 I: Integer; … … 166 243 for I := 0 to Modules.Count - 1 do 167 244 with TModule(Modules[I]) do begin 168 if (Dependencies.IndexOf(ModuleName) <> - 1) and Running then Stop; 169 end; 170 end; 171 172 procedure TModuleManager.EnumModulesStart(Dependencies, 173 ModuleList: TStringList); 174 var 175 Module: TModule; 176 I: Integer; 177 begin 178 for I := 0 to Dependencies.Count - 1 do begin 179 Module := FindModuleByName(Dependencies[I]); 180 if Assigned(Module) then begin 181 if not Module.Running and (ModuleList.IndexOf(Module.Identification) = -1) then begin 182 ModuleList.Add(Module.Identification); 183 EnumModulesStart(Module.Dependencies, ModuleList); 184 end; 185 end else raise Exception.CreateFmt(SModuleNotFound, [Module.Identification]); 186 end; 187 end; 188 189 procedure TModuleManager.EnumModulesStop(ModuleName: string; 190 ModuleList: TStringList); 191 var 192 I: Integer; 193 begin 194 for I := 0 to Modules.Count - 1 do 195 with TModule(Modules[I]) do begin 196 if (Dependencies.IndexOf(ModuleName) <> -1) and Running and 197 (ModuleList.IndexOf(Identification) = -1) then begin 198 ModuleList.Add(Identification); 199 Self.EnumModulesStop(Identification, ModuleList); 245 if (Dependencies.IndexOf(Module.Identification) <> -1) and 246 (ModuleList.IndexOf(TModule(Modules[I])) = -1) and 247 ((mcAll in Conditions) or 248 (Running and (mcRunning in Conditions)) or 249 (not Running and (mcNotRunning in Conditions)) or 250 (Installed and (mcInstalled in Conditions)) or 251 (not Installed and (mcNotInstalled in Conditions)) or 252 (Enabled and (mcEnabled in Conditions)) or 253 (not Enabled and (mcNotEnabled in Conditions))) then begin 254 ModuleList.Add(TModule(Modules[I])); 255 Self.EnumSuperiorDependenciesCascade(TModule(Modules[I]), ModuleList); 200 256 end; 201 257 end; 202 258 end; 203 259 204 procedure TModuleManager.InstallDependencies(ModuleName: string; 205 Dependencies: TStringList); 206 var 207 Module: TModule; 208 I: Integer; 209 begin 210 for I := 0 to Dependencies.Count - 1 do begin 211 Module := FindModuleByName(Dependencies[I]); 212 if Assigned(Module) and Module.Enabled then begin 213 if not Module.Installed then Module.Install; 214 end else raise Exception.CreateFmt(SModuleNotFound, [ModuleName, Dependencies[I]]); 215 end; 216 end; 217 218 procedure TModuleManager.UninstallDependencies(ModuleName: string); 219 var 220 I: Integer; 221 begin 222 for I := 0 to Modules.Count - 1 do 223 with TModule(Modules[I]) do begin 224 if (Dependencies.IndexOf(ModuleName) <> - 1) and Installed then Uninstall; 225 end; 226 end; 227 228 procedure TModuleManager.EnumModulesInstall(Dependencies, 229 ModuleList: TStringList); 230 var 231 Module: TModule; 232 I: Integer; 233 begin 234 for I := 0 to Dependencies.Count - 1 do begin 235 Module := FindModuleByName(Dependencies[I]); 236 if Assigned(Module) then begin 237 if not Module.Installed and (ModuleList.IndexOf(Module.Identification) = -1) then begin 238 ModuleList.Add(Module.Identification); 239 EnumModulesInstall(Module.Dependencies, ModuleList); 240 end; 241 end else raise Exception.CreateFmt(SModuleNotFound, [Module.Identification]); 242 end; 243 end; 244 245 procedure TModuleManager.EnumModulesUninstall(ModuleName: string; 246 ModuleList: TStringList); 247 var 248 I: Integer; 249 begin 250 for I := 0 to Modules.Count - 1 do 251 with TModule(Modules[I]) do begin 252 if (Dependencies.IndexOf(ModuleName) <> -1) and Installed and 253 (ModuleList.IndexOf(Identification) = -1) then begin 254 ModuleList.Add(Identification); 255 Self.EnumModulesUninstall(Identification, ModuleList); 256 end; 257 end; 258 end; 259 260 procedure TModuleManager.RegisterModule(Module: TModule; 261 Enabled: Boolean = True); 260 procedure TModuleManager.RegisterModule(Module: TModule); 262 261 begin 263 262 Modules.Add(Module); 264 263 Module.FManager := Self; 265 264 Module.API := API; 266 Module.Enabled := Enabled;265 Update; 267 266 end; 268 267 … … 270 269 begin 271 270 Modules.Remove(Module); 272 end; 273 274 procedure TModuleManager.StartInstalled; 275 var 276 I: Integer; 277 begin 278 for I := 0 to Modules.Count - 1 do 279 with TModule(Modules[I]) do 280 if not Running and Installed then Start; 281 end; 282 283 procedure TModuleManager.InstallEnabled; 284 var 285 I: Integer; 286 begin 287 for I := 0 to Modules.Count - 1 do 288 with TModule(Modules[I]) do 289 if not Installed and Enabled then Install; 290 end; 291 292 procedure TModuleManager.StopAll; 293 var 294 I: Integer; 295 begin 296 for I := 0 to Modules.Count - 1 do 297 with TModule(Modules[I]) do 298 if Running then Stop; 299 end; 300 301 procedure TModuleManager.UninstallAll; 302 var 303 I: Integer; 304 begin 305 for I := 0 to Modules.Count - 1 do 306 with TModule(Modules[I]) do 307 if Installed then Uninstall; 271 Update; 308 272 end; 309 273 … … 311 275 begin 312 276 inherited; 313 Modules := T ObjectList.Create;314 //Modules.OwnsObjects := False;277 Modules := TListModule.Create; 278 Modules.OwnsObjects := False; 315 279 end; 316 280 317 281 destructor TModuleManager.Destroy; 318 282 begin 319 StopAll;283 Modules.Perform([maStop]); 320 284 FreeAndNil(Modules); 321 285 inherited; … … 332 296 with TModule(Modules[I]) do begin 333 297 OpenKey(Context.Key + '\' + Identification, True); 334 Running := ReadBoolWithDefault('Run',Enabled);298 Enabled := ReadBoolWithDefault('Enable', Enabled); 335 299 end; 336 300 finally … … 347 311 RootKey := Context.RootKey; 348 312 for I := 0 to Modules.Count - 1 do 349 with TModule(Modules[I]) do 350 if Enabled then begin 313 with TModule(Modules[I]) do begin 351 314 OpenKey(Context.Key + '\' + Identification, True); 352 WriteBool(' Run', Running);315 WriteBool('Enable', Enabled); 353 316 end; 354 317 finally 355 318 Free; 356 319 end; 320 end; 321 322 procedure TModuleManager.BeginUpdate; 323 begin 324 Inc(FUpdateCount); 325 end; 326 327 procedure TModuleManager.EndUpdate; 328 begin 329 if FUpdateCount > 0 then Dec(FUpdateCount); 330 if FUpdateCount = 0 then DoUpdate; 331 end; 332 333 procedure TModuleManager.Update; 334 begin 335 if FUpdateCount = 0 then DoUpdate; 357 336 end; 358 337 … … 390 369 end; 391 370 371 procedure TModule.Enable; 372 var 373 List: TListModule; 374 begin 375 if Enabled then Exit; 376 FEnabled := True; 377 try 378 List := TListModule.Create; 379 List.OwnsObjects := False; 380 EnumSuperiorDependenciesCascade(List); 381 List.Perform([maEnable], [mcNotEnabled]); 382 finally 383 List.Free; 384 end; 385 Start; // Auto start enabled modules 386 //Manager.Update; 387 end; 388 389 procedure TModule.Disable; 390 var 391 List: TListModule; 392 begin 393 if not Enabled then Exit; 394 if FRunning then Stop; // Auto stop running modules 395 FEnabled := False; 396 try 397 List := TListModule.Create; 398 List.OwnsObjects := False; 399 EnumSuperiorDependenciesCascade(List); 400 List.Perform([maDisable], [mcEnabled]); 401 finally 402 List.Free; 403 end; 404 Manager.Update; 405 end; 406 392 407 procedure TModule.SetInstalled(AValue: Boolean); 393 408 begin … … 396 411 end; 397 412 413 procedure TModule.SetManager(AValue: TModuleManager); 414 begin 415 if FManager = AValue then Exit; 416 if Assigned(FManager) then FManager.UnregisterModule(Self); 417 FManager := AValue; 418 if Assigned(FManager) then AValue.RegisterModule(Self); 419 end; 420 398 421 procedure TModule.SetEnabled(AValue: Boolean); 399 422 begin 400 423 if FEnabled = AValue then Exit; 401 FEnabled := AValue; 402 if not FEnabled and FInstalled then Uninstall; 424 if FEnabled then Enable else Disable; 403 425 end; 404 426 405 427 procedure TModule.Start; 428 var 429 List: TListModule; 406 430 begin 407 431 if not Enabled or Running then Exit; 408 if not Installed then Install; 409 Manager.StartDependencies(Identification, Dependencies); 432 if not Installed then Install; // Auto install not installed modules 433 try 434 List := TListModule.Create; 435 List.OwnsObjects := False; 436 EnumDependenciesCascade(List); 437 List.Perform([maStart], [mcNotRunning]); 438 finally 439 List.Free; 440 end; 410 441 DoStart; 411 442 FRunning := True; 443 Manager.Update; 412 444 end; 413 445 414 446 procedure TModule.Stop; 447 var 448 List: TListModule; 415 449 begin 416 450 if not Running then Exit; 417 451 FRunning := False; 418 Manager.StopDependencies(Identification); 452 try 453 List := TListModule.Create; 454 List.OwnsObjects := False; 455 EnumSuperiorDependenciesCascade(List); 456 List.Perform([maStop], [mcRunning]); 457 finally 458 List.Free; 459 end; 419 460 DoStop; 461 Manager.Update; 462 end; 463 464 procedure TModule.Restart; 465 begin 466 Stop; 467 Start; 420 468 end; 421 469 422 470 procedure TModule.Install; 423 begin 424 if not Enabled or Installed then Exit; 425 Manager.InstallDependencies(Identification, Dependencies); 471 var 472 List: TListModule; 473 begin 474 if Installed then Exit; 475 try 476 List := TListModule.Create; 477 List.OwnsObjects := False; 478 EnumDependenciesCascade(List); 479 List.Perform([maInstall], [mcNotInstalled]); 480 finally 481 List.Free; 482 end; 426 483 FInstalled := True; 427 if Assigned(Manager.FOnModuleChange) then428 Manager.FOnModuleChange(Manager, Self);429 484 DoInstall; 485 Enable; // Auto enable installed module 486 Manager.Update; 430 487 end; 431 488 432 489 procedure TModule.Uninstall; 490 var 491 List: TListModule; 433 492 begin 434 493 if not Installed then Exit; 435 if Running then Stop; 436 Manager.UninstallDependencies(Identification); 494 if Enabled then Disable; // Auto disable uninstalled module 495 try 496 List := TListModule.Create; 497 List.OwnsObjects := False; 498 EnumSuperiorDependenciesCascade(List); 499 List.Perform([maUninstall], [mcInstalled]); 500 finally 501 List.Free; 502 end; 437 503 FInstalled := False; 438 504 DoUninstall; 439 if Assigned(Manager.FOnModuleChange) then 440 Manager.FOnModuleChange(Manager, Self); 505 Manager.Update; 506 end; 507 508 procedure TModule.Reinstall; 509 begin 510 Uninstall; 511 Install; 441 512 end; 442 513 … … 450 521 Start; 451 522 end else DoUpgrade; 452 end; 453 454 procedure TModule.EnumModulesStart(ModuleList: TStringList); 523 Manager.Update; 524 end; 525 526 procedure TModule.EnumDependenciesCascade(ModuleList: TListModule; 527 Conditions: TModuleConditions = [mcAll]); 455 528 begin 456 529 ModuleList.Clear; 457 Manager.EnumModulesStart(Dependencies, ModuleList); 458 end; 459 460 procedure TModule.EnumModulesStop(ModuleList: TStringList); 530 Manager.EnumDependenciesCascade(Self, ModuleList, Conditions); 531 end; 532 533 procedure TModule.EnumSuperiorDependenciesCascade(ModuleList: TListModule; 534 Conditions: TModuleConditions = [mcAll]); 461 535 begin 462 536 ModuleList.Clear; 463 Manager.EnumModulesStop(Identification, ModuleList); 464 end; 465 466 procedure TModule.EnumModulesInstall(ModuleList: TStringList); 467 begin 468 ModuleList.Clear; 469 Manager.EnumModulesInstall(Dependencies, ModuleList); 470 end; 471 472 procedure TModule.EnumModulesUninstall(ModuleList: TStringList); 473 begin 474 ModuleList.Clear; 475 Manager.EnumModulesUninstall(Identification, ModuleList); 537 Manager.EnumSuperiorDependenciesCascade(Self, ModuleList, Conditions); 476 538 end; 477 539 … … 479 541 begin 480 542 FInstalled := Value; 481 if Assigned(Manager.FOnModuleChange) then 482 Manager.FOnModuleChange(Manager, Self); 543 Manager.Update; 483 544 end; 484 545 … … 486 547 begin 487 548 inherited; 488 Dependencies := T StringList.Create;489 Description := T StringList.Create;549 Dependencies := TListString.Create; 550 Description := TListString.Create; 490 551 end; 491 552
Note:
See TracChangeset
for help on using the changeset viewer.