| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- (* _ _
- * | |__ _ __ ___ ___ | | __
- * | '_ \| '__/ _ \ / _ \| |/ /
- * | |_) | | | (_) | (_) | <
- * |_.__/|_| \___/ \___/|_|\_\
- *
- * Microframework which helps to develop web Pascal applications.
- *
- * Copyright (c) 2012-2021 Silvio Clecio <[email protected]>
- *
- * Brook framework is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * Brook framework is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Brook framework; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *)
- { Dynamic library loader. }
- unit BrookLibraryLoader;
- {$I BrookDefines.inc}
- interface
- uses
- SysUtils,
- Classes,
- libsagui,
- BrookHandledClasses,
- BrookUtility;
- resourcestring
- { Indicates not allowed operation when the library loader is loaded. }
- SBrookActiveLibLoader = 'Active library loader.';
- type
- { Class for dynamic library loading. }
- TBrookLibraryLoader = class(TBrookHandledComponent)
- public const
- { Default library name. }
- LIB_NAME = SG_LIB_NAME;
- private
- FActive: Boolean;
- FVersion: string;
- FHandle: TLibHandle;
- FLibraryName: TFileName;
- FStreamedActive: Boolean;
- FOnLoad: TNotifyEvent;
- FOnUnload: TNotifyEvent;
- function IsActiveStored: Boolean;
- function IsLibraryNameStored: Boolean;
- procedure SetActive(AValue: Boolean);
- procedure SetLibraryName(const AValue: TFileName);
- procedure InternalOpen; {$IFNDEF DEBUG}inline;{$ENDIF}
- procedure InternalLibUnloadEvent(ASender: TObject);
- protected
- procedure Loaded; override;
- procedure CheckInactive; {$IFNDEF DEBUG}inline;{$ENDIF}
- function GetHandle: Pointer; override;
- public
- { Creates an instance of @code(TBrookLibraryLoader).
- @param(AOwner[in] Owner component.) }
- constructor Create(AOwner: TComponent); override;
- { Destroys an instance of @code(TBrookLibraryLoader). }
- destructor Destroy; override;
- { Loads the library dynamically.
- @param(ALibraryName Library name.) }
- class procedure Load(const ALibraryName: TFileName); overload; static;
- { Loads the library dynamically. }
- class procedure Load; overload; static;
- { Unloads the library dynamically. }
- class procedure Unload; static;
- { Checks if the library is already loaded. }
- class function IsLoaded: Boolean; static;
- { Loads the library dynamically. }
- procedure Open; virtual;
- { Unloads the library dynamically. }
- procedure Close; virtual;
- { @exclude }
- procedure DefineProperties(AFiler: TFiler); override;
- published
- { Loads/Unloads the library dynamically. }
- property Active: Boolean read FActive write SetActive stored IsActiveStored;
- { Specifies the library to be loaded dynamically. }
- property LibraryName: TFileName read FLibraryName write SetLibraryName
- stored IsLibraryNameStored;
- { Version of the loaded library. }
- property Version: string read FVersion stored False;
- { Notifies that the library is loaded. }
- property OnLoad: TNotifyEvent read FOnLoad write FOnLoad;
- { Notifies that the library is unloaded. }
- property OnUnload: TNotifyEvent read FOnUnload write FOnUnload;
- end;
- implementation
- constructor TBrookLibraryLoader.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- SgLib.UnloadEvents.Add(InternalLibUnloadEvent, Self);
- FLibraryName := SG_LIB_NAME;
- end;
- destructor TBrookLibraryLoader.Destroy;
- begin
- Close;
- SgLib.UnloadEvents.Remove(InternalLibUnloadEvent);
- inherited Destroy;
- end;
- procedure TBrookLibraryLoader.InternalLibUnloadEvent(ASender: TObject);
- begin
- if Assigned(ASender) then
- begin
- FActive := False;
- FVersion := '';
- end;
- end;
- procedure TBrookLibraryLoader.CheckInactive;
- begin
- if not (csLoading in ComponentState) and Active then
- raise EInvalidOpException.Create(SBrookActiveLibLoader);
- end;
- procedure TBrookLibraryLoader.InternalOpen;
- begin
- FHandle := SgLib.Load(FLibraryName);
- FActive := FHandle <> NilHandle;
- if FActive then
- FVersion := Sagui.VersionStr
- else
- FVersion := '';
- if Assigned(FOnLoad) then
- FOnLoad(Self);
- end;
- procedure TBrookLibraryLoader.Loaded;
- begin
- inherited Loaded;
- if FActive then
- Open;
- end;
- procedure TBrookLibraryLoader.DefineProperties(AFiler: TFiler);
- begin
- inherited DefineProperties(AFiler);
- if FActive and not FStreamedActive then
- begin
- FStreamedActive := True;
- InternalOpen;
- end;
- end;
- function TBrookLibraryLoader.GetHandle: Pointer;
- begin
- Result := @FHandle;
- end;
- class procedure TBrookLibraryLoader.Load(const ALibraryName: TFileName);
- begin
- SgLib.Load(ALibraryName);
- end;
- class procedure TBrookLibraryLoader.Load;
- begin
- SgLib.Load(LIB_NAME);
- end;
- class procedure TBrookLibraryLoader.Unload;
- begin
- SgLib.Unload;
- end;
- class function TBrookLibraryLoader.IsLoaded: Boolean;
- begin
- Result := SgLib.IsLoaded;
- end;
- procedure TBrookLibraryLoader.SetActive(AValue: Boolean);
- begin
- if AValue = FActive then
- Exit;
- if csLoading in ComponentState then
- begin
- SgLib.Unload;
- FActive := AValue;
- end
- else
- if AValue then
- Open
- else
- Close;
- end;
- function TBrookLibraryLoader.IsActiveStored: Boolean;
- begin
- Result := FActive;
- end;
- function TBrookLibraryLoader.IsLibraryNameStored: Boolean;
- begin
- Result := CompareText(FLibraryName, SG_LIB_NAME) <> 0;
- end;
- procedure TBrookLibraryLoader.SetLibraryName(const AValue: TFileName);
- begin
- if AValue = FLibraryName then
- Exit;
- CheckInactive;
- FLibraryName := AValue;
- if FLibraryName = '' then
- FLibraryName := SG_LIB_NAME;
- end;
- procedure TBrookLibraryLoader.Open;
- begin
- if FActive then
- Exit;
- SgLib.Unload;
- InternalOpen;
- end;
- procedure TBrookLibraryLoader.Close;
- begin
- if not FActive then
- Exit;
- FHandle := SgLib.Unload;
- FActive := FHandle <> NilHandle;
- if not FActive then
- FVersion := '';
- if Assigned(FOnUnload) then
- FOnUnload(Self);
- end;
- end.
|