123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- {
- This file is part of the Free Component Library
- Ext.Direct support - http independent part
- Copyright (c) 2007 by Michael Van Canneyt [email protected]
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program 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.
- **********************************************************************}
- unit fpdispextdirect;
- {$mode objfpc}{$H+}
- interface
- uses
- Classes, SysUtils, fpjson, fpjsonrpc ;
- Const
- DefaultExtDirectOptions = DefaultDispatchOptions + [jdoRequireClass];
- Type
- { TCustomExtDirectDispatcher }
- TCustomExtDirectDispatcher = Class(TCustomJSONRPCDispatcher)
- private
- FAPIType: String;
- FNameSpace: String;
- FURL: String;
- function GetNameSpace: String;
- function isNameSpaceStored: boolean;
- Protected
- // Use this to initialize the container when the handler was created.
- Procedure InitContainer(H: TCustomJSONRPCHandler; AContext: TJSONRPCCallContext; AContainer: TComponent); virtual;
- // Format the result
- function FormatResult(const AClassName, AMethodName: TJSONStringType; const Params, ID, Return: TJSONData): TJSONData; override;
- // Called during API creation. Can be used to restrict list of reported handlers.
- Function PublishHandler(H: TCustomJSONRPCHandler): Boolean; virtual;
- // Called during API creation. Can be used to restrict list of reported handlers.
- Function PublishHandlerDef(HD: TJSONRPCHandlerDef): Boolean; virtual;
- // 'tid'
- Class Function TransactionProperty : String; override;
- // 'method'
- Class Function MethodProperty : String; override;
- // 'action'
- Class Function ClassNameProperty : String; override;
- // 'data'
- Class Function ParamsProperty : String; override;
- // Add session support
- Function FindHandler(Const AClassName,AMethodName : TJSONStringType;AContext : TJSONRPCCallContext; Out FreeObject : TComponent) : TCustomJSONRPCHandler; override;
- // Add type field
- function CreateJSON2Error(Const AMessage : String; Const ACode : Integer; ID : TJSONData = Nil; idname : TJSONStringType = 'id' ) : TJSONObject; override;
- // Create API method description
- Function HandlerToAPIMethod (H: TCustomJSONRPCHandler): TJSONObject; virtual;
- Function HandlerDefToAPIMethod (H: TJSONRPCHandlerDef): TJSONObject; virtual;
- // Create API
- Function DoAPI : TJSONData; virtual;
- // Namespace for API description. Must be set. Default 'FPWeb'
- Property NameSpace : String Read GetNameSpace Write FNameSpace Stored isNameSpaceStored;
- // URL property for router. Must be set
- Property URL : String Read FURL Write FURL;
- // "type". By default: 'remoting'
- Property APIType : String Read FAPIType Write FAPIType;
- Public
- // Override to set additional opions.
- Constructor Create(AOwner : TComponent); override;
- // Return API description object
- Function API: TJSONData;
- // Return API Description including namespace, as a string
- Function APIAsString(Formatted : Boolean = False) : String; virtual;
- end;
- { TExtDirectDispatcher }
- TExtDirectDispatcher = Class(TCustomExtDirectDispatcher)
- Published
- Property NameSpace;
- Property URL;
- Property APIType;
- Property OnStartBatch;
- Property OnDispatchRequest;
- Property OnFindHandler;
- Property OnEndBatch;
- Property Options;
- end;
- implementation
- {$ifdef EXTDEBUG}
- uses
- dbugintf;
- {$endif}
- { TCustomExtDirectDispatcher }
- Const
- DefaultNameSpace = 'FPWeb';
- function TCustomExtDirectDispatcher.GetNameSpace: String;
- begin
- Result:=FNameSpace;
- If (Result='') then
- Result:=DefaultNameSpace
- end;
- function TCustomExtDirectDispatcher.isNameSpaceStored: boolean;
- begin
- Result:=NameSpace<>DefaultNameSpace;
- end;
- function TCustomExtDirectDispatcher.FormatResult(const AClassName,
- AMethodName: TJSONStringType; const Params, ID, Return: TJSONData): TJSONData;
- begin
- Result:=Inherited FormatResult(AClassName,AMethodName,Params,ID,Return);
- TJSONObject(Result).Add('type','rpc');
- TJSONObject(Result).Add('action',AClassName);
- TJSONObject(Result).Add('method',AMethodName);
- end;
- Class Function TCustomExtDirectDispatcher.TransactionProperty: String;
- begin
- Result:='tid';
- end;
- Class Function TCustomExtDirectDispatcher.MethodProperty: String;
- begin
- Result:='method';
- end;
- Class Function TCustomExtDirectDispatcher.ClassNameProperty: String;
- begin
- Result:='action';
- end;
- Class Function TCustomExtDirectDispatcher.ParamsProperty: String;
- begin
- Result:='data';
- end;
- Procedure TCustomExtDirectDispatcher.InitContainer(H : TCustomJSONRPCHandler; AContext : TJSONRPCCallContext; AContainer : TComponent);
- begin
- // Do nothing, must be overridden in descendents
- end;
- Function TCustomExtDirectDispatcher.FindHandler(Const AClassName,
- AMethodName: TJSONStringType; AContext: TJSONRPCCallContext; Out
- FreeObject: TComponent): TCustomJSONRPCHandler;
- begin
- {$ifdef extdebug}SendDebugFmt('Searching for %s %s',[AClassName,AMethodName]);{$endif}
- Result:=inherited FindHandler(AClassName, AMethodName, AContext, FreeObject);
- InitContainer(Result,AContext,FreeObject);
- {$ifdef extdebug}SendDebugFmt('Done with searching for %s %s : %d',[AClassName,AMethodName,Ord(Assigned(Result))]);{$endif}
- end;
- function TCustomExtDirectDispatcher.CreateJSON2Error(Const AMessage: String;
- Const ACode: Integer; ID: TJSONData; idname: TJSONStringType): TJSONObject;
- begin
- Result:=inherited CreateJSON2Error(AMessage,ACode,ID,idname);
- TJSONObject(Result).Add('type','rpc');
- end;
- Function TCustomExtDirectDispatcher.HandlerToAPIMethod(H: TCustomJSONRPCHandler
- ): TJSONObject;
- begin
- Result:=TJSONObject.Create(['name',H.Name,'len',H.ParamDefs.Count])
- end;
- Function TCustomExtDirectDispatcher.HandlerDefToAPIMethod(H: TJSONRPCHandlerDef
- ): TJSONObject;
- begin
- Result:=TJSONObject.Create(['name',H.HandlerMethodName,'len',H.ArgumentCount])
- end;
- Function TCustomExtDirectDispatcher.PublishHandler(H : TCustomJSONRPCHandler) : Boolean;
- begin
- Result:=(H<>Nil); // Avoid warning
- end;
- Function TCustomExtDirectDispatcher.PublishHandlerDef(HD : TJSONRPCHandlerDef) : Boolean;
- begin
- Result:=(HD<>Nil); // Avoid warning
- end;
- Function TCustomExtDirectDispatcher.DoAPI: TJSONData;
- Var
- A,D : TJSONObject;
- R : TJSONArray;
- N : TJSONStringType;
- H : TCustomJSONRPCHandler;
- I,J : Integer;
- M : TCustomJSONRPCHandlerManager;
- HD : TJSONRPCHandlerDef;
- begin
- {$ifdef extdebug}SendDebugFmt('Creating API entries',[]);{$endif}
- D:=TJSONObject.Create;
- try
- D.Add('url',URL);
- D.Add('type',APIType);
- A:=TJSONObject.Create;
- D.Add('actions',A);
- R:=Nil;
- N:='';
- If (jdoSearchOwner in Options) and Assigned(Owner) then
- begin
- for I:=Owner.ComponentCount-1 downto 0 do
- If Owner.Components[i] is TCustomJSONRPCHandler then
- begin
- H:=Owner.Components[i] as TCustomJSONRPCHandler;
- if PublishHandler(H) then
- begin
- If (R=Nil) then
- begin
- N:=Owner.Name;
- R:=TJSONArray.Create;
- A.Add(N,R);
- end;
- R.Add(HandlerToAPIMethod(H));
- end;
- end;
- end;
- If (jdoSearchRegistry in Options) then
- begin
- M:=JSONRPCHandlerManager;
- For I:=M.HandlerCount-1 downto 0 do
- begin
- HD:=M.HandlerDefs[i];
- if PublishHandlerDef(HD) then
- begin
- If (R=Nil) or (CompareText(N,HD.HandlerClassName)<>0) then
- begin
- N:=HD.HandlerClassName;
- J:=A.IndexOfName(N);
- If (J=-1) then
- begin
- R:=TJSONArray.Create;
- A.Add(N,R);
- end
- else
- R:=A.Items[J] as TJSONArray;
- end;
- R.Add(HandlerDefToAPIMethod(HD));
- end;
- end;
- end;
- Result:=D;
- except
- FreeAndNil(D);
- Raise;
- end;
- end;
- Constructor TCustomExtDirectDispatcher.Create(AOwner: TComponent);
- Var
- O : TJSONRPCDispatchOptions;
- begin
- inherited Create(AOwner);
- Options:=DefaultExtDirectOptions;
- APIType:='remoting';
- end;
- Function TCustomExtDirectDispatcher.API: TJSONData;
- begin
- Result:=DoAPI;
- end;
- Function TCustomExtDirectDispatcher.APIAsString(Formatted: Boolean = False): String;
- Var
- A : TJSONData;
- begin
- A:=API;
- try
- if Formatted then
- Result:=NameSpace + ' = ' + A.FormatJSON + ';'
- else
- Result:=NameSpace + ' = ' + A.AsJSON + ';';
- finally
- A.Free;
- end;
- end;
- end.
|