fpdispextdirect.pp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. {
  2. This file is part of the Free Component Library
  3. Ext.Direct support - http independent part
  4. Copyright (c) 2007 by Michael Van Canneyt [email protected]
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit fpdispextdirect;
  12. {$mode objfpc}{$H+}
  13. interface
  14. uses
  15. Classes, SysUtils, fpjson, fpjsonrpc ;
  16. Const
  17. DefaultExtDirectOptions = DefaultDispatchOptions + [jdoRequireClass];
  18. Type
  19. { TCustomExtDirectDispatcher }
  20. TCustomExtDirectDispatcher = Class(TCustomJSONRPCDispatcher)
  21. private
  22. FAPIType: String;
  23. FNameSpace: String;
  24. FURL: String;
  25. function GetNameSpace: String;
  26. function isNameSpaceStored: boolean;
  27. Protected
  28. // Use this to initialize the container when the handler was created.
  29. Procedure InitContainer(H: TCustomJSONRPCHandler; AContext: TJSONRPCCallContext; AContainer: TComponent); virtual;
  30. // Format the result
  31. function FormatResult(const AClassName, AMethodName: TJSONStringType; const Params, ID, Return: TJSONData): TJSONData; override;
  32. // Called during API creation. Can be used to restrict list of reported handlers.
  33. Function PublishHandler(H: TCustomJSONRPCHandler): Boolean; virtual;
  34. // Called during API creation. Can be used to restrict list of reported handlers.
  35. Function PublishHandlerDef(HD: TJSONRPCHandlerDef): Boolean; virtual;
  36. // 'tid'
  37. Class Function TransactionProperty : String; override;
  38. // 'method'
  39. Class Function MethodProperty : String; override;
  40. // 'action'
  41. Class Function ClassNameProperty : String; override;
  42. // 'data'
  43. Class Function ParamsProperty : String; override;
  44. // Add session support
  45. Function FindHandler(Const AClassName,AMethodName : TJSONStringType;AContext : TJSONRPCCallContext; Out FreeObject : TComponent) : TCustomJSONRPCHandler; override;
  46. // Add type field
  47. function CreateJSON2Error(Const AMessage : String; Const ACode : Integer; ID : TJSONData = Nil; idname : TJSONStringType = 'id' ) : TJSONObject; override;
  48. // Create API method description
  49. Function HandlerToAPIMethod (H: TCustomJSONRPCHandler): TJSONObject; virtual;
  50. Function HandlerDefToAPIMethod (H: TJSONRPCHandlerDef): TJSONObject; virtual;
  51. // Create API
  52. Function DoAPI : TJSONData; virtual;
  53. // Namespace for API description. Must be set. Default 'FPWeb'
  54. Property NameSpace : String Read GetNameSpace Write FNameSpace Stored isNameSpaceStored;
  55. // URL property for router. Must be set
  56. Property URL : String Read FURL Write FURL;
  57. // "type". By default: 'remoting'
  58. Property APIType : String Read FAPIType Write FAPIType;
  59. Public
  60. // Override to set additional opions.
  61. Constructor Create(AOwner : TComponent); override;
  62. // Return API description object
  63. Function API: TJSONData;
  64. // Return API Description including namespace, as a string
  65. Function APIAsString(Formatted : Boolean = False) : String; virtual;
  66. end;
  67. { TExtDirectDispatcher }
  68. TExtDirectDispatcher = Class(TCustomExtDirectDispatcher)
  69. Published
  70. Property NameSpace;
  71. Property URL;
  72. Property APIType;
  73. Property OnStartBatch;
  74. Property OnDispatchRequest;
  75. Property OnFindHandler;
  76. Property OnEndBatch;
  77. Property Options;
  78. end;
  79. implementation
  80. {$ifdef EXTDEBUG}
  81. uses
  82. dbugintf;
  83. {$endif}
  84. { TCustomExtDirectDispatcher }
  85. Const
  86. DefaultNameSpace = 'FPWeb';
  87. function TCustomExtDirectDispatcher.GetNameSpace: String;
  88. begin
  89. Result:=FNameSpace;
  90. If (Result='') then
  91. Result:=DefaultNameSpace
  92. end;
  93. function TCustomExtDirectDispatcher.isNameSpaceStored: boolean;
  94. begin
  95. Result:=NameSpace<>DefaultNameSpace;
  96. end;
  97. function TCustomExtDirectDispatcher.FormatResult(const AClassName,
  98. AMethodName: TJSONStringType; const Params, ID, Return: TJSONData): TJSONData;
  99. begin
  100. Result:=Inherited FormatResult(AClassName,AMethodName,Params,ID,Return);
  101. TJSONObject(Result).Add('type','rpc');
  102. TJSONObject(Result).Add('action',AClassName);
  103. TJSONObject(Result).Add('method',AMethodName);
  104. end;
  105. Class Function TCustomExtDirectDispatcher.TransactionProperty: String;
  106. begin
  107. Result:='tid';
  108. end;
  109. Class Function TCustomExtDirectDispatcher.MethodProperty: String;
  110. begin
  111. Result:='method';
  112. end;
  113. Class Function TCustomExtDirectDispatcher.ClassNameProperty: String;
  114. begin
  115. Result:='action';
  116. end;
  117. Class Function TCustomExtDirectDispatcher.ParamsProperty: String;
  118. begin
  119. Result:='data';
  120. end;
  121. Procedure TCustomExtDirectDispatcher.InitContainer(H : TCustomJSONRPCHandler; AContext : TJSONRPCCallContext; AContainer : TComponent);
  122. begin
  123. // Do nothing, must be overridden in descendents
  124. end;
  125. Function TCustomExtDirectDispatcher.FindHandler(Const AClassName,
  126. AMethodName: TJSONStringType; AContext: TJSONRPCCallContext; Out
  127. FreeObject: TComponent): TCustomJSONRPCHandler;
  128. begin
  129. {$ifdef extdebug}SendDebugFmt('Searching for %s %s',[AClassName,AMethodName]);{$endif}
  130. Result:=inherited FindHandler(AClassName, AMethodName, AContext, FreeObject);
  131. InitContainer(Result,AContext,FreeObject);
  132. {$ifdef extdebug}SendDebugFmt('Done with searching for %s %s : %d',[AClassName,AMethodName,Ord(Assigned(Result))]);{$endif}
  133. end;
  134. function TCustomExtDirectDispatcher.CreateJSON2Error(Const AMessage: String;
  135. Const ACode: Integer; ID: TJSONData; idname: TJSONStringType): TJSONObject;
  136. begin
  137. Result:=inherited CreateJSON2Error(AMessage,ACode,ID,idname);
  138. TJSONObject(Result).Add('type','rpc');
  139. end;
  140. Function TCustomExtDirectDispatcher.HandlerToAPIMethod(H: TCustomJSONRPCHandler
  141. ): TJSONObject;
  142. begin
  143. Result:=TJSONObject.Create(['name',H.Name,'len',H.ParamDefs.Count])
  144. end;
  145. Function TCustomExtDirectDispatcher.HandlerDefToAPIMethod(H: TJSONRPCHandlerDef
  146. ): TJSONObject;
  147. begin
  148. Result:=TJSONObject.Create(['name',H.HandlerMethodName,'len',H.ArgumentCount])
  149. end;
  150. Function TCustomExtDirectDispatcher.PublishHandler(H : TCustomJSONRPCHandler) : Boolean;
  151. begin
  152. Result:=(H<>Nil); // Avoid warning
  153. end;
  154. Function TCustomExtDirectDispatcher.PublishHandlerDef(HD : TJSONRPCHandlerDef) : Boolean;
  155. begin
  156. Result:=(HD<>Nil); // Avoid warning
  157. end;
  158. Function TCustomExtDirectDispatcher.DoAPI: TJSONData;
  159. Var
  160. A,D : TJSONObject;
  161. R : TJSONArray;
  162. N : TJSONStringType;
  163. H : TCustomJSONRPCHandler;
  164. I,J : Integer;
  165. M : TCustomJSONRPCHandlerManager;
  166. HD : TJSONRPCHandlerDef;
  167. begin
  168. {$ifdef extdebug}SendDebugFmt('Creating API entries',[]);{$endif}
  169. D:=TJSONObject.Create;
  170. try
  171. D.Add('url',URL);
  172. D.Add('type',APIType);
  173. A:=TJSONObject.Create;
  174. D.Add('actions',A);
  175. R:=Nil;
  176. N:='';
  177. If (jdoSearchOwner in Options) and Assigned(Owner) then
  178. begin
  179. for I:=Owner.ComponentCount-1 downto 0 do
  180. If Owner.Components[i] is TCustomJSONRPCHandler then
  181. begin
  182. H:=Owner.Components[i] as TCustomJSONRPCHandler;
  183. if PublishHandler(H) then
  184. begin
  185. If (R=Nil) then
  186. begin
  187. N:=Owner.Name;
  188. R:=TJSONArray.Create;
  189. A.Add(N,R);
  190. end;
  191. R.Add(HandlerToAPIMethod(H));
  192. end;
  193. end;
  194. end;
  195. If (jdoSearchRegistry in Options) then
  196. begin
  197. M:=JSONRPCHandlerManager;
  198. For I:=M.HandlerCount-1 downto 0 do
  199. begin
  200. HD:=M.HandlerDefs[i];
  201. if PublishHandlerDef(HD) then
  202. begin
  203. If (R=Nil) or (CompareText(N,HD.HandlerClassName)<>0) then
  204. begin
  205. N:=HD.HandlerClassName;
  206. J:=A.IndexOfName(N);
  207. If (J=-1) then
  208. begin
  209. R:=TJSONArray.Create;
  210. A.Add(N,R);
  211. end
  212. else
  213. R:=A.Items[J] as TJSONArray;
  214. end;
  215. R.Add(HandlerDefToAPIMethod(HD));
  216. end;
  217. end;
  218. end;
  219. Result:=D;
  220. except
  221. FreeAndNil(D);
  222. Raise;
  223. end;
  224. end;
  225. Constructor TCustomExtDirectDispatcher.Create(AOwner: TComponent);
  226. Var
  227. O : TJSONRPCDispatchOptions;
  228. begin
  229. inherited Create(AOwner);
  230. Options:=DefaultExtDirectOptions;
  231. APIType:='remoting';
  232. end;
  233. Function TCustomExtDirectDispatcher.API: TJSONData;
  234. begin
  235. Result:=DoAPI;
  236. end;
  237. Function TCustomExtDirectDispatcher.APIAsString(Formatted: Boolean = False): String;
  238. Var
  239. A : TJSONData;
  240. begin
  241. A:=API;
  242. try
  243. if Formatted then
  244. Result:=NameSpace + ' = ' + A.FormatJSON + ';'
  245. else
  246. Result:=NameSpace + ' = ' + A.AsJSON + ';';
  247. finally
  248. A.Free;
  249. end;
  250. end;
  251. end.