Componentes.Terceros.RemObj.../internal/5.0.23.613/1/RemObjects SDK for Delphi/Source/uRORemoteDataModule.pas

372 lines
12 KiB
ObjectPascal
Raw Normal View History

unit uRORemoteDataModule;
{----------------------------------------------------------------------------}
{ RemObjects SDK Library - Core Library }
{ }
{ compiler: Delphi 5 and up, Kylix 2 and up }
{ platform: Win32, Linux }
{ }
{ (c)opyright RemObjects Software. all rights reserved. }
{ }
{ Using this code requires a valid license of the RemObjects SDK }
{ which can be obtained at http://www.remobjects.com. }
{----------------------------------------------------------------------------}
{$I RemObjects.inc}
interface
uses
Classes,
{$IFDEF MSWINDOWS}Windows,{$ENDIF}
{$IFDEF DELPHI5}Forms,{$ENDIF}
// {$IFDEF FPC}Forms,{$ENDIF}
uROServerIntf, uROClientIntf, uROSessions, uROClasses, uROTypes, uROEventRepository, uROClient;
type { Events }
TActivateEvent = procedure(const aClientID : TGUID; aSession : TROSession; const aMessage : IROMessage) of object;
TDeactivateEvent = procedure(const aClientID : TGUID; aSession : TROSession) of object;
TGetDispatchInfoEvent = procedure(const aTransport : IROTransport; const aMessage : IROMessage) of object;
TRegisterEventClientEvent = procedure(const aClientID : TGUID; const EventTypes : string) of object;
{ TRORemoteDataModule }
TRORemoteDataModule = class(TDataModule, IROObjectActivation, IRODispatchNotifier, IROServerEventsBroker, IInterface, IROObjectRetainer)
private
fRefCount : integer;
fClientID: TGUID;
fOnActivate: TActivateEvent;
fOnDeactivate: TDeactivateEvent;
fSessionManager : TROCustomSessionManager;
fSession: TROSession;
fNewSession,
fRequiresSession,
fDestroySession : boolean;
fOnGetDispatchInfo: TGetDispatchInfoEvent;
fEventRepository: TROEventRepository;
fOnBeforeUnregisterEventClient: TRegisterEventClientEvent;
fOnBeforeRegisterEventClient: TRegisterEventClientEvent;
fTransport: IROTransport;
fRetainedObjects : TList;
procedure SetSessionManager(const Value: TROCustomSessionManager);
procedure SetEventRepository(const Value: TROEventRepository);
function GetSession: TROSession;
function GetEventRepository: TROEventRepository;
protected
{ IInterface }
function QueryInterface(const IID: TGUID; out Obj): HResult; reintroduce; virtual; stdcall;
function _AddRef: Integer; virtual; stdcall;
function _Release: Integer; virtual; stdcall;
{ IRODispatchNotifier }
procedure GetDispatchInfo(const aTransport : IROTransport; const aMessage : IROMessage); virtual;
{ IROObjectActivation }
procedure _OnActivate(aClientID: TGUID; const aMessage : IROMessage);
procedure _OnDeactivate(aClientID: TGUID);
procedure IROObjectActivation.OnActivate = _OnActivate;
procedure IROObjectActivation.OnDeactivate = _OnDeactivate;
{ IROServerEventsBroker }
procedure RegisterEventClient(const ClientID, EventTypes : string);
procedure UnregisterEventClient(const ClientID, EventTypes : string);
function GetEventsData(const ClientID : string; out EventsData : Binary) : integer;
{ IROObjectRetainer }
procedure RetainObject(const anObject : TObject);
function IsRetained(const anObject : TObject) : boolean;
procedure ReleaseObject(const anObject: TObject);
{ Internal }
procedure DoOnActivate(aClientID: TGUID; const aMessage : IROMessage); virtual;
procedure DoOnDeactivate(aClientID: TGUID); virtual;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
function CustomRequireSession(const aMessage : IROMessage) : boolean; virtual;
{$IFDEF DELPHI7UP}
procedure Synchronize(aMethod: TThreadMethod);
{$ENDIF DELPHI7UP}
public
constructor Create(aOwner : TComponent); override;
destructor Destroy; override;
procedure DestroySession;
property RefCount : integer read fRefCount;
property ClientID : TGUID read fClientID write fClientID;
property Transport: IROTransport read fTransport;
property Session : TROSession read GetSession;
property NewSession : boolean read fNewSession;
published
property RequiresSession : boolean read fRequiresSession write fRequiresSession default FALSE;
property SessionManager : TROCustomSessionManager read fSessionManager write SetSessionManager;
property EventRepository : TROEventRepository read GetEventRepository write SetEventRepository;
property OnActivate : TActivateEvent read fOnActivate write fOnActivate;
property OnDeactivate : TDeactivateEvent read fOnDeactivate write fOnDeactivate;
property OnBeforeRegisterEventClient : TRegisterEventClientEvent read fOnBeforeRegisterEventClient write fOnBeforeRegisterEventClient;
property OnBeforeUnregisterEventClient : TRegisterEventClientEvent read fOnBeforeUnregisterEventClient write fOnBeforeUnregisterEventClient;
property OnGetDispatchInfo : TGetDispatchInfoEvent read fOnGetDispatchInfo write fOnGetDispatchInfo;
end;
TRORemoteDataModuleClass = class of TRORemoteDataModule;
implementation
uses
SysUtils,
{$IFDEF DELPHI5}ComObj,{$ENDIF DELPHI5}
uRORes;
constructor TRORemoteDataModule.Create(aOwner: TComponent);
begin
inherited Create(aOwner);
end;
destructor TRORemoteDataModule.Destroy;
begin
FreeAndNIL(fRetainedObjects);
inherited;
end;
function TRORemoteDataModule._AddRef: Integer;
begin
if (csDesigning in ComponentState) then
result := -1
else
result := InterlockedIncrement(fRefCount);
end;
function TRORemoteDataModule._Release: Integer;
begin
if (csDesigning in ComponentState) then begin
result := -1
end
else begin
result := InterlockedDecrement(fRefCount);
if (result=0)
then Destroy;
end;
end;
function TRORemoteDataModule.QueryInterface(const IID: TGUID;
out Obj): HResult;
begin
result := inherited QueryInterface(IID, Obj);
end;
procedure TRORemoteDataModule._OnActivate(aClientID: TGUID; const aMessage : IROMessage);
begin
fClientID := aClientID;
DoOnActivate(aClientID, aMessage); // Loads the session if a session manager is assigned
if Assigned(fOnActivate)
then fOnActivate(aClientID, fSession, aMessage);
end;
procedure TRORemoteDataModule._OnDeactivate(aClientID: TGUID);
begin
if Assigned(fOnDeactivate)
then fOnDeactivate(aClientID, fSession);
DoOnDeactivate(aClientID); // Releases the session
end;
procedure TRORemoteDataModule.DoOnActivate(aClientID: TGUID; const aMessage : IROMessage);
begin
if (csDesigning in ComponentState) then Exit;
fSession := NIL;
if not CustomRequireSession(aMessage) then Exit;
if Assigned(fSessionManager) then begin
fNewSession := FALSE;
fDestroySession := FALSE; // Resets the flags
fSession := fSessionManager.FindSession(aClientID);
if (fSession=NIL) then begin
if RequiresSession
then RaiseError(err_SessionNotFound, [GUIDToString(aClientID)], EROSessionNotFound)
else begin
fSession := fSessionManager.CreateSession(aClientID);
fNewSession := TRUE;
end;
end;
end
else begin
if RequiresSession then
RaiseError('SessionManager required, but not assigned');
end;
end;
procedure TRORemoteDataModule.DoOnDeactivate(aClientID: TGUID);
var
lSessionID: TGUID;
begin
if (csDesigning in ComponentState) then Exit;
if Assigned(fSessionManager) and (fSession<>NIL) then begin
if fDestroySession then begin
if NewSession then begin
fSessionManager.DeleteTemporarySession(fSession)
end
else begin
lSessionID := fSession.SessionID;
fSessionManager.ReleaseSession(fSession, false);
fSessionManager.DeleteSession(lSessionID, false)
end;
end
else begin
fSessionManager.ReleaseSession(fSession, NewSession);
end;
end;
end;
procedure TRORemoteDataModule.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited;
if (Operation=opRemove) then begin
if (AComponent=fSessionManager) then fSessionManager := NIL
else if (AComponent=fEventRepository) then fEventRepository := NIL;
end;
end;
procedure TRORemoteDataModule.DestroySession;
begin
fDestroySession := TRUE;
end;
procedure TRORemoteDataModule.GetDispatchInfo(const aTransport: IROTransport; const aMessage: IROMessage);
begin
if Assigned(fOnGetDispatchInfo) then
fOnGetDispatchInfo(aTransport, aMessage);
fTransport := aTransport;
end;
function TRORemoteDataModule.CustomRequireSession(const aMessage: IROMessage): boolean;
begin
result := not Assigned(aMessage) or not SameText(aMessage.MessageName, 'GetDescriptor');
end;
procedure TRORemoteDataModule.SetSessionManager(
const Value: TROCustomSessionManager);
begin
fSessionManager := Value;
if (fSessionManager<>NIL) then fSessionManager.FreeNotification(Self);
end;
{$IFDEF DELPHI7UP}
procedure TRORemoteDataModule.Synchronize(aMethod: TThreadMethod);
begin
TThread.Synchronize(nil, aMethod);
end;
{$ENDIF DELPHI7UP}
function TRORemoteDataModule.GetEventsData(const ClientID: string; out EventsData: Binary): integer;
begin
result := 0;
if (fEventRepository=NIL) then Exit;
EventsData := Binary.Create;
result := EventRepository.GetEventData(Session.SessionID, EventsData);
end;
procedure TRORemoteDataModule.RegisterEventClient(const ClientID, EventTypes: string);
var
lActive: IROActiveEventServer;
begin
if Assigned(fOnBeforeRegisterEventClient) then
fOnBeforeRegisterEventClient(StringToGUID(ClientID), EventTypes);
if assigned(fEventRepository) then begin
if Supports(Transport, IROActiveEventServer, lActive) then
fEventRepository.AddSession(StringToGUID(ClientID), lActive)
else
fEventRepository.AddSession(StringToGUID(ClientID));
end;
end;
procedure TRORemoteDataModule.UnregisterEventClient(const ClientID, EventTypes: string);
begin
if Assigned(fOnBeforeUnregisterEventClient) then
fOnBeforeUnregisterEventClient(StringToGUID(ClientID), EventTypes);
if assigned(fEventRepository) then
fEventRepository.RemoveSession(StringToGUID(ClientID));
end;
procedure TRORemoteDataModule.SetEventRepository(const Value: TROEventRepository);
begin
if (fEventRepository=Value) then Exit;
fEventRepository := Value;
if (fEventRepository<>NIL) then
fEventRepository.FreeNotification(Self);
end;
function TRORemoteDataModule.GetSession: TROSession;
var errmsg : string;
begin
if not (csDesigning in ComponentState) then begin
if (fSession=NIL) then begin
errmsg := 'The session has not been initialized.';
if SessionManager=NIL then errmsg := errmsg+' '+Name+'''s SessionManager property is set to NIL.';
raise EROException.Create(errmsg);
end;
end;
result := fSession;
end;
function TRORemoteDataModule.GetEventRepository: TROEventRepository;
var errmsg : string;
begin
if not (csDesigning in ComponentState) then begin
if (fEventRepository=NIL) then begin
errmsg := errmsg+' '+Name+'''s EventRepository property is not assigned';
raise EROException.Create(errmsg);
end;
end;
result := fEventRepository;
end;
function TRORemoteDataModule.IsRetained(const anObject: TObject): boolean;
begin
result := (fRetainedObjects<>NIL) and (fRetainedObjects.IndexOf(anObject)>=0)
end;
procedure TRORemoteDataModule.RetainObject(const anObject: TObject);
begin
// Only creates it if necessary
if (fRetainedObjects=NIL) then
fRetainedObjects := TList.Create;
fRetainedObjects.Add(anObject);
end;
procedure TRORemoteDataModule.ReleaseObject(const anObject: TObject);
var idx : integer;
begin
// Only creates it if necessary
if (fRetainedObjects=NIL) then Exit;
idx := fRetainedObjects.IndexOf(anObject);
if (idx>=0) then fRetainedObjects.Delete(idx);
end;
end.