fpwebdata.pp 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2019 by the Free Pascal development team
  4. webdata interface
  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. {$IFNDEF FPC_DOTTEDUNITS}
  12. unit fpwebdata;
  13. {$ENDIF FPC_DOTTEDUNITS}
  14. {$mode objfpc}{$H+}
  15. interface
  16. {$IFDEF FPC_DOTTEDUNITS}
  17. uses
  18. System.Classes, System.SysUtils, FpWeb.Http.Defs, FpWeb.Http.Base, Data.Db;
  19. {$ELSE FPC_DOTTEDUNITS}
  20. uses
  21. Classes, SysUtils, httpdefs, fphttp, db;
  22. {$ENDIF FPC_DOTTEDUNITS}
  23. type
  24. { TWebdataInputAdaptor }
  25. // Translate web request to input for the dataprovider.
  26. // Descendents must adapt the methods so they fit the particular JS/HTML engine used.
  27. TWebDataAction = (wdaUnknown,wdaRead,wdaUpdate,wdaInsert,wdaDelete);
  28. { TCustomWebdataInputAdaptor }
  29. TTransCodeEvent = Procedure (Sender : TObject; Var S : String);
  30. TCustomWebdataInputAdaptor = class(TComponent)
  31. private
  32. FAction: TWebDataAction;
  33. FOntransCode: TTransCodeEvent;
  34. FRequest: TRequest;
  35. FBatchCount : Integer;
  36. FRequestPathInfo : String;
  37. function GetAction: TWebDataAction;
  38. procedure SetRequest(const AValue: TRequest);
  39. Protected
  40. procedure reset; virtual;
  41. Function GetActionFromRequest : TWebDataAction; virtual;
  42. Public
  43. Function GetNextBatch : Boolean; virtual;
  44. Function TryParamValue(Const AParamName : String; out AValue : String) : Boolean; virtual;
  45. Function TryFieldValue(Const AFieldName : String; out AValue : String) : Boolean; virtual;
  46. Function HaveParamValue(Const AParamName : String) : boolean;
  47. Function HaveFieldValue(Const AFieldName : String) : boolean;
  48. Function GetParamValue(Const AParamName : String) : String;
  49. Function GetFieldValue(Const AFieldName : String) : String;
  50. Property Request : TRequest Read FRequest Write SetRequest;
  51. Property Action : TWebDataAction Read GetAction Write FAction;
  52. Property OnTransCode : TTransCodeEvent Read FOntransCode Write FOnTransCode;
  53. end;
  54. TCustomWebdataInputAdaptorClass = Class of TCustomWebdataInputAdaptor;
  55. TWebdataInputAdaptor = Class(TCustomWebdataInputAdaptor)
  56. Private
  57. FInputFormat: String;
  58. FProxy : TCustomWebdataInputAdaptor;
  59. procedure SetInputFormat(const AValue: String);
  60. Protected
  61. Procedure ClearProxy;
  62. Procedure CheckProxy;
  63. Function CreateProxy : TCustomWebdataInputAdaptor; virtual;
  64. Function GetActionFromRequest : TWebDataAction; override;
  65. Public
  66. Destructor Destroy; override;
  67. Function GetNextBatch : Boolean; override;
  68. Function TryParamValue(Const AParamName : String; out AValue : String) : Boolean; override;
  69. Function TryFieldValue(Const AFieldName : String; out AValue : String) : Boolean; override;
  70. Published
  71. Property InputFormat : String Read FInputFormat Write SetInputFormat;
  72. end;
  73. // Manage the data for the content producer
  74. // return a dataset for data, handles update/delete/insert in a simple TDataset manner.
  75. { TFPCustomWebDataProvider }
  76. TWebDataProviderOption = (wdpReadOnly,wdpDisableDelete,wdpDisableEdit,wdpDisableInsert);
  77. TWebDataProviderOptions = set of TWebDataProviderOption;
  78. TFPCustomWebDataProvider = Class(TComponent)
  79. private
  80. FAdaptor: TCustomWebdataInputAdaptor;
  81. FIDFieldName: String;
  82. FOptions: TWebDataProviderOptions;
  83. Protected
  84. // Check if adaptor and dataset are available.
  85. procedure CheckAdaptor;
  86. // Copy data from input to fields in dataset. Can be overridden
  87. Procedure CopyFieldData; virtual;
  88. Procedure DoUpdate; virtual;
  89. Procedure DoDelete; virtual;
  90. Procedure DoInsert; virtual;
  91. // Locate current record. Assumes that
  92. Procedure LocateCurrent; virtual;
  93. Procedure DoApplyParams; virtual;
  94. Function GetDataset : TDataset; virtual; abstract;
  95. Public
  96. // Perform an update on the dataset. Correct record is located first.
  97. Procedure Update;
  98. // Perform a delete on the dataset. Correct record is located first.
  99. Procedure Delete;
  100. // Perform an insert on the dataset.
  101. Procedure Insert;
  102. // Apply any parameters passed from request to the dataset. Used only in read operations
  103. Procedure ApplyParams;
  104. // get ID Field instance from dataset
  105. function GetIDField: TField;
  106. // Get value of ID field as string. After insert, this should contain the newly inserted ID.
  107. Function IDFieldValue : String; virtual;
  108. // The dataset
  109. Property Dataset : TDataset Read GetDataset;
  110. // Input adaptor
  111. property Adaptor : TCustomWebdataInputAdaptor Read FAdaptor Write FAdaptor;
  112. // Fieldname of ID field. If empty, field with pfInKey is searched.
  113. Property IDFieldName : String Read FIDFieldName Write FIDFieldName;
  114. // options
  115. Property Options : TWebDataProviderOptions Read FOptions Write FOptions;
  116. end;
  117. TFPCustomWebDataProviderClass = Class of TFPCustomWebDataProvider;
  118. { TFPWebDataProvider }
  119. // Simple descendent that has a datasource property, can be dropped on a module.
  120. TFPWebDataProvider = Class(TFPCustomWebDataProvider)
  121. private
  122. FDatasource: TDatasource;
  123. procedure SetDataSource(const AValue: TDatasource);
  124. Protected
  125. Function GetDataset : TDataset; override;
  126. Public
  127. procedure Notification(AComponent: TComponent; Operation: TOperation);override;
  128. Published
  129. Property DataSource : TDatasource Read FDatasource Write SetDataSource;
  130. end;
  131. // Handle request for read/create/update/delete and return a result.
  132. { TCustomHTTPDataContentProducer }
  133. // Support for transcoding from/to UTF-8. If outbound is true, the value is going from server to browser.
  134. TOnTranscodeEvent = Procedure (Sender : TObject; F : TField; Var S : String; Outbound : Boolean) of object;
  135. TCustomHTTPDataContentProducer = Class(THTTPContentProducer)
  136. Private
  137. FAllowPageSize: Boolean;
  138. FBeforeDelete: TNotifyEvent;
  139. FBeforeInsert: TNotifyEvent;
  140. FBeforeUpdate: TNotifyEvent;
  141. FDataProvider: TFPCustomWebDataProvider;
  142. FMetadata: Boolean;
  143. FOnTranscode: TOnTranscodeEvent;
  144. FPageSize: Integer;
  145. FPageStart: Integer;
  146. FSD: Boolean;
  147. FSortField: String;
  148. FAdaptor : TCustomWebdataInputAdaptor;
  149. function GetDataset: TDataset;
  150. procedure SetAdaptor(const AValue: TCustomWebDataInputAdaptor);
  151. procedure SetDataProvider(const AValue: TFPCustomWebDataProvider);
  152. Protected
  153. Procedure StartBatch(ResponseContent : TStream); virtual;
  154. Procedure NextBatchItem(ResponseContent : TStream); virtual;
  155. Procedure EndBatch(ResponseContent : TStream); virtual;
  156. Function GetDataContentType : String; virtual;
  157. procedure DatasetToStream(Stream: TStream); virtual;abstract;
  158. Function CreateAdaptor(ARequest : TRequest) : TCustomWebdataInputAdaptor; virtual;
  159. Procedure DoGetContent(ARequest : TRequest; Content : TStream; Var Handled : Boolean); override;
  160. Procedure DoHandleRequest(ARequest : TRequest; AResponse : TResponse; Var Handled : Boolean); override;
  161. Procedure DoUpdateRecord(ResponseContent : TStream); virtual;
  162. Procedure DoInsertRecord(ResponseContent : TStream); virtual;
  163. Procedure DoDeleteRecord(ResponseContent : TStream); virtual;
  164. Procedure DoReadRecords(ResponseContent : TStream); virtual;
  165. Procedure DoExceptionToStream(E : Exception; ResponseContent : TStream); virtual; abstract;
  166. procedure Notification(AComponent: TComponent; Operation: TOperation);override;
  167. Property Dataset: TDataset Read GetDataSet;
  168. // Before a record is about to be updated
  169. Property BeforeUpdate : TNotifyEvent Read FBeforeUpdate Write FBeforeUpdate;
  170. // Before a record is about to be inserted
  171. Property BeforeInsert : TNotifyEvent Read FBeforeInsert Write FBeforeInsert;
  172. // Before a record is about to be deleted
  173. Property BeforeDelete : TNotifyEvent Read FBeforeDelete Write FBeforeDelete;
  174. Public
  175. Constructor Create(AOwner : TComponent); override;
  176. Property Adaptor : TCustomWebDataInputAdaptor Read FAdaptor Write SetAdaptor;
  177. Property Provider : TFPCustomWebDataProvider read FDataProvider write SetDataProvider;
  178. Property DataContentType : String Read GetDataContentType;
  179. Published
  180. Property PageStart : Integer Read FPageStart Write FPageStart default 0;
  181. Property PageSize : Integer Read FPageSize Write FPageSize default 0;
  182. Property MetaData : Boolean Read FMetadata Write FMetaData Default False;
  183. Property SortField : String Read FSortField Write FSortField;
  184. Property SortDescending : Boolean Read FSD Write FSD default False;
  185. Property AllowPageSize : Boolean Read FAllowPageSize Write FAllowPageSize default True;
  186. Property OnTransCode : TOnTranscodeEvent Read FOnTranscode Write FOnTranscode;
  187. end;
  188. TCustomHTTPDataContentProducerClass = Class of TCustomHTTPDataContentProducer;
  189. { THTTPDataContentProducer }
  190. THTTPDataContentProducer = Class(TCustomHTTPDataContentProducer)
  191. private
  192. FOnConfigure: TNotifyEvent;
  193. FProxy : TCustomHTTPDataContentProducer;
  194. FOutputFormat: String;
  195. procedure SetOutputFormat(const AValue: String);
  196. Protected
  197. Procedure ClearProxy;
  198. Procedure CheckProxy;
  199. Function CreateProxy : TCustomHTTPDataContentProducer; virtual;
  200. procedure ConfigureProxy(AProxy: TCustomHTTPDataContentProducer); virtual;
  201. Public
  202. Destructor destroy; override;
  203. Published
  204. Property Adaptor;
  205. Property Provider;
  206. Property OutputFormat : String Read FOutputFormat Write SetOutputFormat;
  207. Property OnConfigureFormat : TNotifyEvent Read FOnConfigure Write FOnConfigure;
  208. end;
  209. TBeforeCreateWebDataProviderEvent = Procedure (Sender : TObject; Var AClass : TFPCustomWebDataProviderClass) of object;
  210. TWebDataProviderEvent = Procedure (Sender : TObject; AProvider : TFPCustomWebDataProvider) of object;
  211. //TWebDataCreateProviderEvent = Procedure (Sender : TObject; Const AProviderName : String; Out AnInstance : TFPCustomWebDataProvider) of object;
  212. TDataModuleClass = Class of TDataModule;
  213. { TWebInputAdaptorDef }
  214. TWebInputAdaptorDef = Class(TCollectionItem)
  215. private
  216. FClass: TCustomWebdataInputAdaptorClass;
  217. FName: String;
  218. procedure SetName(const AValue: String);
  219. protected
  220. Function CreateInstance(AOwner : TComponent) :TCustomWebdataInputAdaptor; virtual;
  221. Public
  222. Property AdaptorClass : TCustomWebdataInputAdaptorClass Read FClass Write FClass;
  223. Property Name : String Read FName Write SetName;
  224. end;
  225. { TWebInputAdaptorDefs }
  226. TWebInputAdaptorDefs = Class(TCollection)
  227. private
  228. function GetD(Index : Integer): TWebInputAdaptorDef;
  229. procedure SetD(Index : Integer; const AValue: TWebInputAdaptorDef);
  230. Public
  231. Function IndexOfAdaptor(Const AAdaptorName : String) : Integer;
  232. Function AddAdaptor(Const AAdaptorName : String; AClass : TCustomWebdataInputAdaptorClass) : TWebInputAdaptorDef;
  233. Property AdaptorDefs[Index : Integer] : TWebInputAdaptorDef Read GetD Write SetD; default;
  234. end;
  235. { THttpDataProducerDef }
  236. THttpDataProducerDef = Class(TCollectionItem)
  237. private
  238. FClass: TCustomHTTPDataContentProducerClass;
  239. FName: String;
  240. procedure SetName(const AValue: String);
  241. protected
  242. Function CreateInstance(AOwner : TComponent) :TCustomHTTPDataContentProducer; virtual;
  243. Public
  244. Property ProducerClass : TCustomHTTPDataContentProducerClass Read FClass Write FClass;
  245. Property Name : String Read FName Write SetName;
  246. end;
  247. { THttpDataProducerDefs }
  248. THttpDataProducerDefs = Class(TCollection)
  249. private
  250. function GetD(Index : Integer): THttpDataProducerDef;
  251. procedure SetD(Index : Integer; const AValue: THttpDataProducerDef);
  252. Public
  253. Function IndexOfProducer(Const AProducerName : String) : Integer;
  254. Function AddProducer(Const AProducerName : String; AClass : TCustomHTTPDataContentProducerClass) : THttpDataProducerDef;
  255. Property ProducerDefs[Index : Integer] : THttpDataProducerDef Read GetD Write SetD; default;
  256. end;
  257. { TWebDataProviderDef }
  258. TWebDataProviderDef = Class(TCollectionItem)
  259. private
  260. FAfterCreate: TWebDataProviderEvent;
  261. FBeforeCreate: TBeforeCreateWebDataProviderEvent;
  262. FPClass: TFPCustomWebDataProviderClass;
  263. FDataModuleClass : TDataModuleClass;
  264. FProviderName: String;
  265. procedure SetFPClass(const AValue: TFPCustomWebDataProviderClass);
  266. procedure SetProviderName(const AValue: String);
  267. protected
  268. Function CreateInstance(AOwner : TComponent; Out AContainer : TComponent) : TFPCUstomWebDataProvider; virtual;
  269. Property DataModuleClass : TDataModuleClass Read FDataModuleClass;
  270. Public
  271. Property ProviderName : String Read FProviderName Write SetProviderName;
  272. Property ProviderClass : TFPCustomWebDataProviderClass Read FPClass Write SetFPClass;
  273. Property BeforeCreate : TBeforeCreateWebDataProviderEvent Read FBeforeCreate Write FBeforeCreate;
  274. Property AfterCreate : TWebDataProviderEvent Read FAfterCreate Write FAfterCreate;
  275. end;
  276. { TWebDataProviderDefs }
  277. TWebDataProviderDefs = Class(TCollection)
  278. private
  279. function GetD(Index : Integer): TWebDataProviderDef;
  280. procedure SetD(Index : Integer; const AValue: TWebDataProviderDef);
  281. Public
  282. Function IndexOfProvider(Const AProviderName : String) : Integer;
  283. Function AddProvider(Const AProviderName : String) : TWebDataProviderDef; overload;
  284. Function AddProvider(Const AProviderName : String; AClass :TFPCustomWebDataProviderClass) : TWebDataProviderDef; overload;
  285. Property WebDataProviderDefs[Index : Integer] : TWebDataProviderDef Read GetD Write SetD; default;
  286. end;
  287. { TFPCustomWebDataProviderManager }
  288. TFPCustomWebDataProviderManager = Class(TComponent)
  289. Private
  290. FRegistering: Boolean;
  291. Protected
  292. procedure Initialize; virtual;
  293. // Provider support
  294. Procedure RemoveProviderDef(Const Index : Integer); virtual; abstract;
  295. function AddProviderDef(Const AProviderName : String) : TWebDataProviderDef; virtual; abstract;
  296. function IndexOfProviderDef(Const AProviderName : String) : Integer; virtual; abstract;
  297. function GetProviderDef(Index : Integer): TWebDataProviderDef; virtual; abstract;
  298. function GetProviderDefCount: Integer; virtual; abstract;
  299. // Inputadaptor support
  300. function AddInputAdaptorDef(Const AAdaptorName : String; AClass : TCustomWebdataInputAdaptorClass) : TWebInputAdaptorDef; virtual; abstract;
  301. function IndexOfInputAdaptorDef(Const AAdaptorName : String) : Integer; virtual; abstract;
  302. Procedure RemoveInputAdaptorDef(Index : Integer); virtual; abstract;
  303. function GetInputAdaptorDef(Index : Integer): TWebInputAdaptorDef; virtual; abstract;
  304. function GetInputAdaptorDefCount: Integer; virtual; abstract;
  305. // Outputproducer support
  306. function AddHttpDataProducerDef(Const AProducerName : String; AClass : TCustomHTTPDataContentProducerClass) : THttpDataProducerDef; virtual; abstract;
  307. function IndexOfHttpDataProducerDef(Const AProducerName : String) : Integer; virtual; abstract;
  308. Procedure RemoveHttpDataProducerDef(Index : Integer); virtual; abstract;
  309. function GetHttpDataProducerDef(Index : Integer): THttpDataProducerDef; virtual; abstract;
  310. function GetHttpDataProducerDefCount: Integer; virtual; abstract;
  311. Public
  312. // Input Provider support
  313. Procedure Unregisterprovider(Const AProviderName : String);
  314. Procedure RegisterDatamodule(Const AClass : TDatamoduleClass);
  315. Function RegisterProvider(Const AProviderName : String; AClass : TFPCustomWebDataProviderClass) : TWebDataProviderDef; overload;
  316. Function FindProviderDefByName(Const AProviderName : String) : TWebDataProviderDef;
  317. Function GetProviderDefByName(Const AProviderName : String) : TWebDataProviderDef;
  318. Function GetProvider(Const ADef : TWebDataProviderDef; AOwner : TComponent; Out AContainer : TComponent): TFPCustomWebDataProvider;
  319. Function GetProvider(Const AProviderName : String; AOwner : TComponent; Out AContainer : TComponent): TFPCustomWebDataProvider;
  320. // Input Adaptor support
  321. Function RegisterInputAdaptor(Const AAdaptorName : String; AClass : TCustomWebdataInputAdaptorClass) : TWebInputAdaptorDef;
  322. Procedure UnRegisterInputAdaptor(Const AAdaptorName : String);
  323. Function FindInputAdaptorDefByName(Const AAdaptorName : String) : TWebInputAdaptorDef;
  324. Function GetInputAdaptorDefByName(Const AAdaptorName : String) : TWebInputAdaptorDef;
  325. Function GetInputAdaptor(Const ADef : TWebInputAdaptorDef; AOwner : TComponent = Nil): TCustomWebdataInputAdaptor; overload;
  326. Function GetInputAdaptor(Const AAdaptorName : String; AOwner : TComponent = Nil): TCustomWebdataInputAdaptor; overload;
  327. // Outputproducer support
  328. function RegisterDataProducer(Const AProducerName : String; AClass : TCustomHTTPDataContentProducerClass) : THttpDataProducerDef;
  329. Procedure UnRegisterDataProducer(Const AProducerName : String);
  330. function FindDataProducerDefByName(Const AProducerName : String) : THttpDataProducerDef;
  331. function GetDataProducerDefByName(Const AProducerName : String) : THttpDataProducerDef;
  332. function GetDataProducer(ADef : THttpDataProducerDef; AOwner : TComponent) : TCustomHTTPDataContentProducer;
  333. function GetDataProducer(Const AProducerName: String; AOwner : TComponent) : TCustomHTTPDataContentProducer;
  334. // properties
  335. Property Registering : Boolean Read FRegistering;
  336. Property ProviderCount : Integer Read GetProviderDefCount;
  337. Property ProviderDefs[Index : Integer] : TWebDataProviderDef Read GetProviderDef;
  338. Property InputAdaptorDefs[Index : Integer] : TWebInputAdaptorDef Read GetInputAdaptorDef;
  339. Property InputAdaptorDefCount : Integer Read GetInputAdaptorDefCount;
  340. Property DataProducerDefs[Index : Integer] : THttpDataProducerDef Read GetHttpDataProducerDef;
  341. Property DataProducerDefCount : Integer Read GetHttpDataProducerDefCount;
  342. end;
  343. TFPCustomWebDataProviderManagerClass = Class of TFPCustomWebDataProviderManager;
  344. { TFPWebDataProviderManager }
  345. TFPWebDataProviderManager = Class(TFPCustomWebDataProviderManager)
  346. Private
  347. FProviderDefs : TWebDataProviderDefs;
  348. FAdaptorDefs : TWebInputAdaptorDefs;
  349. FProducerDefs : THttpDataProducerDefs;
  350. Protected
  351. Procedure RemoveProviderDef(Const Index : Integer); override;
  352. function AddProviderDef(Const AProviderName : String) : TWebDataProviderDef; override;
  353. function IndexOfProviderDef(Const AProviderName : String) : Integer; override;
  354. function GetProviderDef(Index : Integer): TWebDataProviderDef; override;
  355. function GetProviderDefCount: Integer; override;
  356. // Inputadaptor support
  357. function AddInputAdaptorDef(Const AAdaptorName : String; AClass : TCustomWebdataInputAdaptorClass) : TWebInputAdaptorDef; Override;
  358. function IndexOfInputAdaptorDef(Const AAdaptorName : String) : Integer; Override;
  359. procedure RemoveInputAdaptorDef(Index : Integer); Override;
  360. function GetInputAdaptorDef(Index : Integer): TWebInputAdaptorDef; Override;
  361. function GetInputAdaptorDefCount: Integer; Override;
  362. // Outputproducer support
  363. function AddHttpDataProducerDef(Const AProducerName : String; AClass : TCustomHTTPDataContentProducerClass) : THttpDataProducerDef; Override;
  364. function IndexOfHttpDataProducerDef(Const AProducerName : String) : Integer; Override;
  365. Procedure RemoveHttpDataProducerDef(Index : Integer); Override;
  366. function GetHttpDataProducerDef(Index : Integer): THttpDataProducerDef; Override;
  367. function GetHttpDataProducerDefCount: Integer; Override;
  368. Public
  369. Constructor Create(AOwner : TComponent); override;
  370. Destructor Destroy; override;
  371. end;
  372. THandleWebDataEvent = Procedure (Sender : TObject;AProvider : TFPCustomWebDataProvider; Var Handled : Boolean) of object;
  373. TWebDataEvent = Procedure (Sender : TObject; AProvider : TFPCustomWebDataProvider) of object;
  374. TContentProducerEvent = Procedure (Sender : TObject; Var AContentProducer: TCustomHTTPDataContentProducer) of object;
  375. TInputAdaptorEvent = Procedure (Sender : TObject; Var AInputAdaptor : TCustomWebdataInputAdaptor) of object;
  376. TContentEvent = Procedure (Sender : TObject; Content : TStream) of Object;
  377. TGetWebDataProviderEvent = Procedure (Sender : TObject; Const AProviderName : String; Var AnInstance : TFPCustomWebDataProvider) of object;
  378. { TFPCustomWebDataModule }
  379. { TFPCustomWebProviderDataModule }
  380. TFPCustomWebProviderDataModule = Class(TSessionHTTPModule)
  381. Private
  382. FAfterDelete: TWebDataEvent;
  383. FAfterInsert: TWebDataEvent;
  384. FAfterRead: TWebDataEvent;
  385. FAfterUpdate: TWebDataEvent;
  386. FBeforeDelete: THandleWebDataEvent;
  387. FBeforeInsert: THandleWebDataEvent;
  388. FBeforeRead: THandleWebDataEvent;
  389. FBeforeUpdate: THandleWebDataEvent;
  390. FContentProducer: TCustomHTTPDataContentProducer;
  391. FInputAdaptor: TCustomWebdataInputAdaptor;
  392. FOnContent: TContentEvent;
  393. FOnGetContentProducer: TContentProducerEvent;
  394. FOnGetInputAdaptor: TInputAdaptorEvent;
  395. FOnGetProvider: TGetWebDataProviderEvent;
  396. FRequest: TRequest;
  397. FResponse: TResponse;
  398. FUseProviderManager: Boolean;
  399. function GetAdaptor: TCustomWebDataInputAdaptor;
  400. function GetContentProducer: TCustomHTTPDataContentProducer;
  401. Procedure ReadWebData(AProvider : TFPCustomWebDataProvider);
  402. Procedure InsertWebData(AProvider : TFPCustomWebDataProvider);
  403. procedure SetContentProducer(const AValue: TCustomHTTPDataContentProducer);
  404. procedure SetInputAdaptor(const AValue: TCustomWebdataInputAdaptor);
  405. Procedure UpdateWebData(AProvider : TFPCustomWebDataProvider);
  406. Procedure DeleteWebData(AProvider : TFPCustomWebDataProvider);
  407. Protected
  408. function GetProvider(const AProviderName: String; Out AContainer : TComponent): TFPCustomWebDataProvider; virtual;
  409. procedure ProduceContent(AProvider : TFPCustomWebDataProvider); virtual;
  410. Procedure DoReadWebData(AProvider : TFPCustomWebDataProvider); virtual;
  411. Procedure DoInsertWebData(AProvider : TFPCustomWebDataProvider); virtual;
  412. Procedure DoUpdateWebData(AProvider : TFPCustomWebDataProvider); virtual;
  413. Procedure DoDeleteWebData(AProvider : TFPCustomWebDataProvider); virtual;
  414. // Input adaptor to use when processing request. Can be nil, and provided in OnGetInputAdaptor
  415. Property InputAdaptor : TCustomWebdataInputAdaptor Read FInputAdaptor Write SetInputAdaptor;
  416. // Content producer to produce response content
  417. Property ContentProducer : TCustomHTTPDataContentProducer Read FContentProducer Write SetContentProducer;
  418. // Triggered before a read request is started
  419. Property BeforeRead : THandleWebDataEvent Read FBeforeRead Write FBeforeRead;
  420. // Triggered after a read request completed
  421. Property AfterRead : TWebDataEvent Read FAfterRead Write FAfterRead;
  422. // Triggered before an insert request is started
  423. Property BeforeInsert : THandleWebDataEvent Read FBeforeInsert Write FBeforeInsert;
  424. // Triggered after an insert request completed
  425. Property AfterInsert : TWebDataEvent Read FAfterInsert Write FAfterInsert;
  426. // Triggered before an update request is started
  427. Property BeforeUpdate : THandleWebDataEvent Read FBeforeUpdate Write FBeforeUpdate;
  428. // Triggered after an update request completed
  429. Property AfterUpdate : TWebDataEvent Read FAfterUpdate Write FAfterUpdate;
  430. // Triggered before a delete request is started
  431. Property BeforeDelete : THandleWebDataEvent Read FBeforeDelete Write FBeforeDelete;
  432. // Triggered after an insert request completed
  433. Property AfterDelete : TWebDataEvent Read FAfterDelete Write FAfterDelete;
  434. // Triggered when the input adaptor needs to be determined.
  435. Property OnGetInputAdaptor : TInputAdaptorEvent Read FOnGetInputAdaptor Write FOnGetInputAdaptor;
  436. // Triggered when the WebDataProvider needs to be determined.
  437. Property OnGetProvider : TGetWebDataProviderEvent Read FOnGetProvider Write FOnGetprovider;
  438. // Triggered when the contentproducer needs to be determined
  439. Property OnGetContentProducer : TContentProducerEvent Read FOnGetContentProducer Write FOnGetContentProducer;
  440. // Triggered when the content has been created.
  441. Property OnContent : TContentEvent Read FOnContent Write FOnContent;
  442. // Set to False if the ProviderManager should not be searched for a provider
  443. Property UseProviderManager : Boolean Read FUseProviderManager Write FUseProviderManager default True;
  444. Public
  445. Constructor CreateNew(AOwner : TComponent; CreateMode : Integer); override;
  446. Procedure HandleRequest(ARequest : TRequest; AResponse : TResponse); override;
  447. // Access to request
  448. Property Request: TRequest Read FRequest;
  449. // Access to response
  450. Property Response: TResponse Read FResponse;
  451. end;
  452. TFPWebProviderDataModule = Class(TFPCustomWebProviderDataModule)
  453. Published
  454. Property Kind;
  455. Property BaseURL;
  456. Property AfterInitModule;
  457. Property Session;
  458. Property CreateSession;
  459. Property InputAdaptor;
  460. Property ContentProducer;
  461. Property UseProviderManager;
  462. Property OnGetContentProducer;
  463. Property BeforeRead;
  464. Property AfterRead;
  465. Property BeforeInsert;
  466. Property AfterInsert;
  467. Property BeforeUpdate;
  468. Property AfterUpdate;
  469. Property BeforeDelete;
  470. Property AfterDelete;
  471. Property OnGetInputAdaptor;
  472. Property OnGetProvider;
  473. Property OnContent;
  474. Property OnNewSession;
  475. Property OnSessionExpired;
  476. property CORS;
  477. end;
  478. Var
  479. WebDataProviderManagerClass : TFPCustomWebDataProviderManagerClass = TFPWebDataProviderManager;
  480. Function WebDataProviderManager : TFPCustomWebDataProviderManager;
  481. implementation
  482. { $define wmdebug}
  483. {$ifdef wmdebug}
  484. uses dbugintf;
  485. {$endif}
  486. Resourcestring
  487. SErrNoIDField = 'No key field found';
  488. SErrNoAdaptor = 'No adaptor assigned';
  489. SErrNoDataset = 'No dataset assigned';
  490. SErrNoIDValue = 'No key value specified';
  491. SErrCouldNotLocateRecord = 'Could not locate record with value "%s" for key field "%s"';
  492. SErrNoDatasource = 'No datasource property available';
  493. SErrNoAction = 'Cannot determine action from request';
  494. SErrDuplicateWebDataProvider = 'Duplicate webdata provider';
  495. SErrUnknownWebDataProvider = 'Unknown webdata provider: "%s"';
  496. SErrContentProviderRequest = 'Content provider "%s" does not handle request.';
  497. SErrUnknownProviderAction = 'Cannot determine action for provider "%s".';
  498. SErrDuplicateAdaptor = 'Duplicate input adaptor name: "%s"';
  499. SErrDuplicateHTTPDataProducer = 'Duplicate web data output content producer name: "%s"';
  500. SErrUnknownInputAdaptor = 'Unknown web data input adaptor name: "%s"';
  501. SErrUnknownHTTPDataProducer = 'Unknown web data output content producer name: "%s"';
  502. SErrActionNotAllowed = 'Options of provider %s do not allow %s.';
  503. SEditing = 'editing';
  504. SDeleting = 'deleting';
  505. SInserting = 'inserting';
  506. { TCustomWebdataInputAdaptor }
  507. { TFPCustomWebDataProvider }
  508. procedure TCustomWebdataInputAdaptor.SetRequest(const AValue: TRequest);
  509. begin
  510. If FRequest=AValue then Exit;
  511. FRequest:=AValue;
  512. Reset;
  513. end;
  514. procedure TCustomWebdataInputAdaptor.reset;
  515. begin
  516. {$ifdef wmdebug}SendDebugFmt('TCustomWebdataInputAdaptor.Reset (%s)',[FRequestPathInfo]);{$endif}
  517. FBatchCount:=0;
  518. Faction:=wdaUnknown;
  519. FRequestPathInfo:='';
  520. end;
  521. function TCustomWebdataInputAdaptor.GetActionFromRequest: TWebDataAction;
  522. Var
  523. N : String;
  524. begin
  525. Result:=wdaUnknown;
  526. If (Request<>Nil) then
  527. begin
  528. if (FRequestPathInfo='') then
  529. FRequestPathInfo:=Request.GetNextPathInfo;
  530. N:=lowercase(FRequestPathInfo);
  531. {$ifdef wmdebug}SendDebugFmt('TCustomWebdataInputAdaptor.GetActionFromRequest : %s (%s)',[n,Request.Pathinfo]);{$endif}
  532. If (N='read') then
  533. Result:=wdaRead
  534. else If (N='insert') then
  535. Result:=wdaInsert
  536. else If (N='delete') then
  537. Result:=wdaDelete
  538. else If (N='update') then
  539. Result:=wdaUpdate;
  540. end;
  541. end;
  542. function TCustomWebdataInputAdaptor.GetAction: TWebDataAction;
  543. begin
  544. If (Faction=wdaUnknown) then
  545. FAction:=GetActionFromRequest;
  546. Result:=FAction;
  547. If (Result=wdaUnknown) then
  548. Raise EFPHTTPError.Create(SErrNoAction)
  549. end;
  550. function TCustomWebdataInputAdaptor.GetNextBatch: Boolean;
  551. begin
  552. Result:=(FBatchCount=0);
  553. Inc(FBatchCount);
  554. end;
  555. function TCustomWebdataInputAdaptor.TryParamValue(const AParamName: String;
  556. out AValue: String): Boolean;
  557. Var
  558. L : TStrings;
  559. I : Integer;
  560. N : String;
  561. begin
  562. Result:=False;
  563. If (Request.Method='GET') then
  564. L:=Request.QueryFields
  565. else // (Request.Method='POST') then
  566. L:=FRequest.ContentFields;
  567. I:=L.IndexOfName(AParamName);
  568. Result:=(I<>-1);
  569. If Result then
  570. L.GetNameValue(I,N,AValue);
  571. If (AValue<>'') and Assigned(FOnTranscode) then
  572. FOnTransCode(Self,Avalue);
  573. end;
  574. function TCustomWebdataInputAdaptor.TryFieldValue(const AFieldName: String;
  575. out AValue: String): Boolean;
  576. begin
  577. Result:=TryParamValue(AFieldName,AValue);
  578. end;
  579. function TCustomWebdataInputAdaptor.HaveParamValue(const AParamName: String
  580. ): boolean;
  581. Var
  582. S: String;
  583. begin
  584. Result:=TryParamValue(AParamName,S);
  585. end;
  586. function TCustomWebdataInputAdaptor.HaveFieldValue(const AFieldName: String
  587. ): Boolean;
  588. Var
  589. S: String;
  590. begin
  591. Result:=TryFieldValue(AFieldName,S);
  592. end;
  593. function TCustomWebdataInputAdaptor.GetParamValue(const AParamName: String): String;
  594. begin
  595. If not TryParamValue(AParamName,Result) then
  596. Result:='';
  597. end;
  598. function TCustomWebdataInputAdaptor.GetFieldValue(const AFieldName: String): String;
  599. begin
  600. If not TryFieldValue(AFieldName,Result) then
  601. Result:='';
  602. end;
  603. { TFPCustomWebDataProvider }
  604. procedure TFPCustomWebDataProvider.CopyFieldData;
  605. Var
  606. I : Integer;
  607. F : TField;
  608. S : String;
  609. DS : TDataset;
  610. begin
  611. DS:=Dataset;
  612. For I:=0 to DS.Fields.Count-1 do
  613. begin
  614. F:=DS.Fields[i];
  615. If (F.DataType<>ftAutoInc) or (DS.State=dsInsert) then
  616. If ADaptor.TryFieldValue(F.FieldName,S) then
  617. begin
  618. If (S<>'') then
  619. F.AsString:=S
  620. else if DS.State=dsEdit then
  621. F.Clear;
  622. end;
  623. end;
  624. end;
  625. procedure TFPCustomWebDataProvider.DoUpdate;
  626. Var
  627. DS : TDataset;
  628. begin
  629. {$ifdef wmdebug}SendDebug('TFPCustomWebDataProvider.DoUpdate: Updating record');{$endif}
  630. DS:=Dataset;
  631. LocateCurrent;
  632. DS.Edit;
  633. CopyFieldData;
  634. DS.Post;
  635. {$ifdef wmdebug}SendDebug('TFPCustomWebDataProvider.DoUpdate: Done Updating record');{$endif}
  636. end;
  637. procedure TFPCustomWebDataProvider.DoDelete;
  638. Var
  639. DS : TDataset;
  640. begin
  641. {$ifdef wmdebug}SendDebug('TFPCustomWebDataProvider.DoDelete: Deleting record');{$endif}
  642. LocateCurrent;
  643. DS:=Dataset;
  644. DS.Delete;
  645. end;
  646. procedure TFPCustomWebDataProvider.DoInsert;
  647. Var
  648. DS : TDataset;
  649. begin
  650. {$ifdef wmdebug}SendDebug('TFPCustomWebDataProvider.DoInsert: Inserting record');{$endif}
  651. DS:=Dataset;
  652. DS.Append;
  653. CopyFieldData;
  654. DS.Post;
  655. end;
  656. Function TFPCustomWebDataProvider.GetIDField : TField;
  657. Var
  658. FN : String;
  659. I : Integer;
  660. begin
  661. Result:=Nil;
  662. FN:=IDFieldName;
  663. If (FN='') then
  664. begin
  665. I:=0;
  666. While (Result=Nil) and (I<Dataset.Fields.Count) do
  667. begin
  668. If pfInKey in Dataset.Fields[i].ProviderFLags then
  669. Result:=Dataset.Fields[i];
  670. inc(I);
  671. end;
  672. end
  673. else
  674. Result:=Dataset.FieldByname(FN);
  675. if (Result=Nil) then
  676. Raise EFPHTTPError.Create(SErrNoIDField);
  677. end;
  678. procedure TFPCustomWebDataProvider.LocateCurrent;
  679. Var
  680. V : String;
  681. F : TField;
  682. begin
  683. CheckAdaptor;
  684. F:=GetIDField;
  685. V:=Adaptor.GetFieldValue(F.FieldName);
  686. If (V='') then
  687. Raise EFPHTTPError.Create(SErrNoIDValue);
  688. if Not Dataset.Locate(F.FieldName,V,[]) then
  689. begin
  690. // Search the hard way
  691. Dataset.First;
  692. While (not Dataset.EOF) and (F.AsString<>V) do
  693. Dataset.Next;
  694. If Dataset.EOF and (F.AsString<>V) then
  695. Raise EFPHTTPError.CreateFmt(SErrCouldNotLocateRecord,[V,F.FieldName]);
  696. end;
  697. end;
  698. procedure TFPCustomWebDataProvider.DoApplyParams;
  699. begin
  700. // Do nothing
  701. end;
  702. procedure TFPCustomWebDataProvider.CheckAdaptor;
  703. begin
  704. if Not Assigned(Adaptor) then
  705. Raise EFPHTTPError.Create(SErrNoAdaptor);
  706. if Not Assigned(Dataset) then
  707. Raise EFPHTTPError.Create(SerrNoDataset);
  708. end;
  709. procedure TFPCustomWebDataProvider.Update;
  710. begin
  711. {$ifdef wmdebug}SendDebug('TFPCustomWebDataProvider.Update enter');{$endif}
  712. If ((Options * [wdpReadOnly,wdpDisableEdit])<>[]) then
  713. Raise EFPHTTPError.CreateFmt(SErrActionNotAllowed,[Name,SEditing]);
  714. CheckAdaptor;
  715. DoUpdate;
  716. {$ifdef wmdebug}SendDebug('TFPCustomWebDataProvider.Update leave');{$endif}
  717. end;
  718. procedure TFPCustomWebDataProvider.Delete;
  719. begin
  720. {$ifdef wmdebug}SendDebug('TFPCustomWebDataProvider.Delete enter');{$endif}
  721. If ((Options * [wdpReadOnly,wdpDisableDelete])<>[]) then
  722. Raise EFPHTTPError.CreateFmt(SErrActionNotAllowed,[Name,SDeleting]);
  723. CheckAdaptor;
  724. DoDelete;
  725. {$ifdef wmdebug}SendDebug('TFPCustomWebDataProvider.Delete leave');{$endif}
  726. end;
  727. procedure TFPCustomWebDataProvider.Insert;
  728. begin
  729. {$ifdef wmdebug}SendDebug('TFPCustomWebDataProvider.Insert enter');{$endif}
  730. If ((Options * [wdpReadOnly,wdpDisableInsert])<>[]) then
  731. Raise EFPHTTPError.CreateFmt(SErrActionNotAllowed,[Name,SInserting]);
  732. CheckAdaptor;
  733. DoInsert;
  734. {$ifdef wmdebug}SendDebug('TFPCustomWebDataProvider.Insert leave');{$endif}
  735. end;
  736. procedure TFPCustomWebDataProvider.ApplyParams;
  737. begin
  738. CheckAdaptor;
  739. DoApplyParams;
  740. end;
  741. function TFPCustomWebDataProvider.IDFieldValue: String;
  742. begin
  743. Result:=GetIDField.DisplayText;
  744. end;
  745. { TFPWebDataProvider }
  746. procedure TFPWebDataProvider.SetDataSource(const AValue: TDatasource);
  747. begin
  748. if FDataSource=AValue then exit;
  749. If Assigned(FDatasource) then
  750. FDataSource.RemoveFreeNotification(Self);
  751. FDataSource:=AValue;
  752. If Assigned(FDatasource) then
  753. FDataSource.FreeNotification(Self);
  754. end;
  755. function TFPWebDataProvider.GetDataset: TDataset;
  756. begin
  757. If Assigned(DataSource) then
  758. Result:=Datasource.Dataset
  759. else
  760. Raise EFPHTTPError.Create(SErrNoDatasource)
  761. end;
  762. procedure TFPWebDataProvider.Notification(AComponent: TComponent;
  763. Operation: TOperation);
  764. begin
  765. If (Operation=opRemove) and (AComponent=FDatasource) then
  766. FDatasource:=Nil;
  767. inherited Notification(AComponent, Operation);
  768. end;
  769. { TCustomHTTPDataContentProducer }
  770. function TCustomHTTPDataContentProducer.GetDataset: TDataset;
  771. begin
  772. If Assigned(FDataProvider) then
  773. Result:=FDataProvider.Dataset;
  774. end;
  775. procedure TCustomHTTPDataContentProducer.SetAdaptor(
  776. const AValue: TCustomWebDataInputAdaptor);
  777. begin
  778. If FAdaptor=AValue then
  779. exit;
  780. If Assigned(FAdaptor) then
  781. FAdaptor.RemoveFreeNotification(Self);
  782. FAdaptor:=AValue;
  783. If Assigned(FAdaptor) then
  784. FAdaptor.FreeNotification(Self);
  785. end;
  786. procedure TCustomHTTPDataContentProducer.Notification(AComponent: TComponent;
  787. Operation: TOperation);
  788. begin
  789. If (Operation=opRemove) then
  790. if (AComponent=FDataProvider) then
  791. FDataProvider:=Nil
  792. else if (AComponent=FAdaptor) then
  793. FAdaptor:=Nil;
  794. inherited Notification(AComponent, Operation);
  795. end;
  796. procedure TCustomHTTPDataContentProducer.SetDataProvider(
  797. const AValue: TFPCustomWebDataProvider);
  798. begin
  799. if FDataProvider=AValue then exit;
  800. If Assigned(FDataProvider) then
  801. FDataProvider.RemoveFreeNotification(Self);
  802. FDataProvider:=AValue;
  803. If Assigned(FDataProvider) then
  804. FDataProvider.FreeNotification(Self);
  805. end;
  806. procedure TCustomHTTPDataContentProducer.StartBatch(ResponseContent: TStream);
  807. begin
  808. // Do nothing
  809. end;
  810. procedure TCustomHTTPDataContentProducer.NextBatchItem(ResponseContent: TStream
  811. );
  812. begin
  813. // do nothing
  814. end;
  815. procedure TCustomHTTPDataContentProducer.EndBatch(ResponseContent: TStream);
  816. begin
  817. // do nothing
  818. end;
  819. function TCustomHTTPDataContentProducer.GetDataContentType: String;
  820. begin
  821. Result:='';
  822. end;
  823. function TCustomHTTPDataContentProducer.CreateAdaptor(ARequest : TRequest): TCustomWebdataInputAdaptor;
  824. begin
  825. Result:=TCustomWebdataInputAdaptor.Create(Self);
  826. Result.Request:=ARequest
  827. end;
  828. procedure TCustomHTTPDataContentProducer.DoGetContent(ARequest : TRequest; Content : TStream; Var Handled : Boolean);
  829. Var
  830. B : Boolean;
  831. A : TCustomWebdataInputAdaptor;
  832. begin
  833. {$ifdef wmdebug}SendDebugFmt('Request content %s',[ARequest.Content]);{$endif}
  834. B:=(Adaptor=Nil);
  835. if B then
  836. begin
  837. A:=CreateAdaptor(ARequest);
  838. Adaptor:=A;
  839. end;
  840. try
  841. try
  842. Case Adaptor.Action of
  843. wdaRead : DoReadRecords(Content);
  844. wdaInsert,
  845. wdaUpdate,
  846. wdaDelete :
  847. begin
  848. {$ifdef wmdebug}SendDebug('Starting batch Loop');{$endif}
  849. StartBatch(Content);
  850. While Adaptor.GetNextBatch do
  851. begin
  852. {$ifdef wmdebug}SendDebug('Next batch item');{$endif}
  853. NextBatchItem(Content);
  854. Case Adaptor.Action of
  855. wdaInsert : DoInsertRecord(Content);
  856. wdaUpdate : DoUpdateRecord(Content);
  857. wdaDelete : DoDeleteRecord(Content);
  858. else
  859. inherited DoGetContent(ARequest, Content,Handled);
  860. end;
  861. end;
  862. EndBatch(Content);
  863. {$ifdef wmdebug}SendDebug('Ended batch Loop');{$endif}
  864. end;
  865. else
  866. Raise EFPHTTPError.Create(SErrNoAction);
  867. end;
  868. Handled:=true;
  869. except
  870. On E : Exception do
  871. begin
  872. DoExceptionToStream(E,Content);
  873. Handled:=True;
  874. end;
  875. end;
  876. finally
  877. If B then
  878. FreeAndNil(A);
  879. end;
  880. end;
  881. procedure TCustomHTTPDataContentProducer.DoHandleRequest(ARequest: TRequest;
  882. AResponse: TResponse; var Handled: Boolean);
  883. Var
  884. S : String;
  885. begin
  886. inherited DoHandleRequest(ARequest, AResponse, Handled);
  887. If Handled then
  888. begin
  889. S:=GetDataContentType;
  890. If (S<>'') then
  891. AResponse.ContentType:=S;
  892. end;
  893. end;
  894. procedure TCustomHTTPDataContentProducer.DoUpdateRecord(ResponseContent: TStream);
  895. begin
  896. {$ifdef wmdebug}SendDebug('DoUpdateRecord: Updating record');{$endif}
  897. If Assigned(FBeforeUpdate) then
  898. FBeforeUpdate(Self);
  899. Provider.Update;
  900. {$ifdef wmdebug}SendDebug('DoUpdateRecord: Updated record');{$endif}
  901. end;
  902. procedure TCustomHTTPDataContentProducer.DoInsertRecord(ResponseContent: TStream);
  903. begin
  904. If Assigned(FBeforeInsert) then
  905. FBeforeInsert(Self);
  906. Provider.Insert;
  907. end;
  908. procedure TCustomHTTPDataContentProducer.DoDeleteRecord(ResponseContent: TStream);
  909. begin
  910. If Assigned(FBeforeDelete) then
  911. FBeforeDelete(Self);
  912. Provider.Delete;
  913. end;
  914. procedure TCustomHTTPDataContentProducer.DoReadRecords(ResponseContent: TStream);
  915. Var
  916. DS : TDataset;
  917. begin
  918. DS:=Provider.Dataset;
  919. If Not DS.Active then
  920. begin
  921. {$ifdef wmdebug}SendDebug('Doreadrecords: Applying parameters');{$endif}
  922. Provider.ApplyParams;
  923. {$ifdef wmdebug}SendDebug('Doreadrecords: Applied parameters');{$endif}
  924. DS.Open;
  925. {$ifdef wmdebug}SendDebug('Doreadrecords: opened dataset');{$endif}
  926. end;
  927. DatasetToStream(ResponseContent);
  928. end;
  929. constructor TCustomHTTPDataContentProducer.Create(AOwner: TComponent);
  930. begin
  931. inherited Create(AOwner);
  932. FAllowPagesize:=True;
  933. end;
  934. { TWebDataProviderDef }
  935. procedure TWebDataProviderDef.SetFPClass(
  936. const AValue: TFPCustomWebDataProviderClass);
  937. begin
  938. if FPClass=AValue then exit;
  939. FPClass:=AValue;
  940. end;
  941. procedure TWebDataProviderDef.SetProviderName(const AValue: String);
  942. begin
  943. if FProviderName=AValue then exit;
  944. FProviderName:=AValue;
  945. end;
  946. Function TWebDataProviderDef.CreateInstance(AOwner: TComponent; Out AContainer : TComponent) : TFPCUstomWebDataProvider;
  947. Var
  948. AClass : TFPCustomWebDataProviderClass;
  949. DM : TDataModule;
  950. C : TComponent;
  951. begin
  952. Result:=Nil;
  953. {$ifdef wmdebug}SendDebug(Format('Creating instance for %s',[Self.ProviderName]));{$endif}
  954. If Assigned(FDataModuleClass) then
  955. begin
  956. {$ifdef wmdebug}SendDebug(Format('Creating datamodule from class %d ',[Ord(Assigned(FDataModuleClass))]));{$endif}
  957. DM:=FDataModuleClass.Create(AOwner);
  958. {$ifdef wmdebug}SendDebug(Format('Created datamodule from class %s ',[DM.ClassName]));{$endif}
  959. C:=DM.FindComponent(FProviderName);
  960. If (C<>Nil) and (C is TFPCUstomWebDataProvider) then
  961. Result:=TFPCUstomWebDataProvider(C)
  962. else
  963. begin
  964. FreeAndNil(DM);
  965. Raise EFPHTTPError.CreateFmt(SErrUnknownWebDataProvider,[FProviderName]);
  966. end;
  967. end
  968. else
  969. DM:=TDataModule.CreateNew(AOwner,0);
  970. AContainer:=DM;
  971. If (Result=Nil) then
  972. begin
  973. {$ifdef wmdebug}SendDebug(Format('Creating from class pointer %d ',[Ord(Assigned(FPClass))]));{$endif}
  974. AClass:=FPCLass;
  975. If Assigned(FBeforeCreate) then
  976. FBeforeCreate(Self,AClass);
  977. Result:=AClass.Create(AContainer);
  978. end;
  979. If Assigned(FAfterCreate) then
  980. FAfterCreate(Self,Result);
  981. end;
  982. { TWebDataProviderDefs }
  983. function TWebDataProviderDefs.GetD(Index : Integer): TWebDataProviderDef;
  984. begin
  985. Result:=TWebDataProviderDef(Items[Index])
  986. end;
  987. procedure TWebDataProviderDefs.SetD(Index : Integer;
  988. const AValue: TWebDataProviderDef);
  989. begin
  990. Items[Index]:=AValue;
  991. end;
  992. function TWebDataProviderDefs.IndexOfProvider(const AProviderName: String
  993. ): Integer;
  994. begin
  995. Result:=Count-1;
  996. While (Result>=0) and (CompareText(GetD(Result).ProviderName,AProviderName)<>0) do
  997. Dec(Result);
  998. end;
  999. function TWebDataProviderDefs.AddProvider(const AProviderName: String
  1000. ): TWebDataProviderDef;
  1001. begin
  1002. If IndexOfProvider(AProviderName)=-1 then
  1003. begin
  1004. Result:=Add as TWebDataProviderDef;
  1005. Result.ProviderName:=AProviderName;
  1006. end
  1007. else
  1008. Raise EFPHTTPError.CreateFmt(SErrDuplicateWebDataProvider,[AProviderName]);
  1009. end;
  1010. function TWebDataProviderDefs.AddProvider(const AProviderName: String;
  1011. AClass: TFPCustomWebDataProviderClass): TWebDataProviderDef;
  1012. begin
  1013. Result:=AddProvider(AProviderName);
  1014. Result.ProviderClass:=AClass;
  1015. end;
  1016. Var
  1017. AWebDataProviderManager : TFPCustomWebDataProviderManager;
  1018. Function WebDataProviderManager : TFPCustomWebDataProviderManager;
  1019. begin
  1020. If (AWebDataProviderManager=Nil) then
  1021. begin
  1022. If WebDataProviderManagerClass=Nil then
  1023. WebDataProviderManagerClass:=TFPWebDataProviderManager;
  1024. AWebDataProviderManager:=WebDataProviderManagerClass.Create(Nil);
  1025. AWebDataProviderManager.Initialize;
  1026. end;
  1027. Result:=AWebDataProviderManager;
  1028. end;
  1029. { TFPCustomWebDataProviderManager }
  1030. procedure TFPCustomWebDataProviderManager.Initialize;
  1031. begin
  1032. // Do nothing
  1033. end;
  1034. procedure TFPCustomWebDataProviderManager.Unregisterprovider(
  1035. const AProviderName: String);
  1036. Var
  1037. I : Integer;
  1038. begin
  1039. I:=IndexOfProviderDef(AProviderName);
  1040. If (I<>-1) then
  1041. RemoveProviderDef(I)
  1042. else
  1043. Raise EFPHTTPError.CreateFmt(SErrUnknownWebDataProvider,[AProviderName]);
  1044. end;
  1045. procedure TFPCustomWebDataProviderManager.RegisterDatamodule(
  1046. const AClass: TDatamoduleClass);
  1047. Var
  1048. DM : TDatamodule;
  1049. I,J : Integer;
  1050. C : TComponent;
  1051. D : TWebDataProviderDef;
  1052. begin
  1053. FRegistering:=True;
  1054. try
  1055. DM:=AClass.Create(Self);
  1056. try
  1057. For I:=0 to DM.ComponentCount-1 do
  1058. begin
  1059. C:=DM.Components[i];
  1060. if C is TFPCustomWebDataProvider then
  1061. begin
  1062. J:=IndexOfProviderDef(C.Name);
  1063. If (J<>-1) then
  1064. Raise EFPHTTPError.CreateFmt(SErrDuplicateWebDataProvider,[C.Name]);
  1065. D:=AddProviderDef(C.Name);
  1066. {$ifdef wmdebug}SendDebug('Registering provider '+C.Name);{$endif}
  1067. D.FDataModuleClass:=TDataModuleClass(DM.ClassType);
  1068. end;
  1069. end;
  1070. finally
  1071. DM.Free;
  1072. end;
  1073. finally
  1074. FRegistering:=False;
  1075. end;
  1076. end;
  1077. function TFPCustomWebDataProviderManager.RegisterProvider(
  1078. const AProviderName: String; AClass: TFPCustomWebDataProviderClass
  1079. ): TWebDataProviderDef;
  1080. Var
  1081. I : Integer;
  1082. begin
  1083. FRegistering:=True;
  1084. try
  1085. I:=IndexOfProviderDef(AProviderName);
  1086. If (I<>-1) then
  1087. Raise EFPHTTPError.CreateFmt(SErrDuplicateWebDataProvider,[AProviderName]);
  1088. Result:=AddProviderDef(AProviderName);
  1089. Result.ProviderClass:=AClass;
  1090. finally
  1091. FRegistering:=False;
  1092. end;
  1093. end;
  1094. function TFPCustomWebDataProviderManager.FindProviderDefByName(
  1095. const AProviderName: String): TWebDataProviderDef;
  1096. Var
  1097. I : integer;
  1098. begin
  1099. I:=IndexOfProviderDef(AProviderName);
  1100. If (I=-1) then
  1101. Result:=Nil
  1102. else
  1103. Result:=GetProviderDef(I);
  1104. end;
  1105. function TFPCustomWebDataProviderManager.GetProviderDefByName(
  1106. const AProviderName: String): TWebDataProviderDef;
  1107. begin
  1108. Result:=FindProviderDefByName(AProviderName);
  1109. If (Result=Nil) then
  1110. Raise EFPHTTPError.CreateFmt(SErrUnknownWebDataProvider,[AProviderName]);
  1111. end;
  1112. function TFPCustomWebDataProviderManager.GetProvider(
  1113. const AProviderName: String; AOwner: TComponent; Out AContainer : TComponent): TFPCustomWebDataProvider;
  1114. Var
  1115. D : TWebDataProviderDef;
  1116. begin
  1117. D:=GetProviderDefByname(AProviderName);
  1118. Result:=GetProvider(D,AOwner,AContainer);
  1119. end;
  1120. function TFPCustomWebDataProviderManager.RegisterInputAdaptor(
  1121. const AAdaptorName: String; AClass: TCustomWebdataInputAdaptorClass
  1122. ): TWebInputAdaptorDef;
  1123. begin
  1124. If IndexOfInputAdaptorDef(AAdaptorName)<>-1 then
  1125. Raise EFPHTTPError.CreateFmt(SErrDuplicateAdaptor,[AAdaptorName]);
  1126. Result:=AddInputAdaptorDef(AAdaptorName,AClass);
  1127. end;
  1128. procedure TFPCustomWebDataProviderManager.UnRegisterInputAdaptor(
  1129. const AAdaptorName: String);
  1130. Var
  1131. I : Integer;
  1132. begin
  1133. I:=IndexOfInputAdaptorDef(AAdaptorName);
  1134. If (I<>-1) then
  1135. RemoveInputAdaptorDef(I);
  1136. end;
  1137. function TFPCustomWebDataProviderManager.FindInputAdaptorDefByName(
  1138. const AAdaptorName: String): TWebInputAdaptorDef;
  1139. Var
  1140. I: integer;
  1141. begin
  1142. I:=IndexOfInputAdaptorDef(AAdaptorName);
  1143. If I<>-1 then
  1144. Result:=GetInputAdaptorDef(I)
  1145. else
  1146. Result:=Nil;
  1147. end;
  1148. function TFPCustomWebDataProviderManager.GetInputAdaptorDefByName(
  1149. const AAdaptorName: String): TWebInputAdaptorDef;
  1150. begin
  1151. Result:=FindInputAdaptorDefByName(AAdaptorName);
  1152. If (Result=Nil) then
  1153. Raise EFPHTTPError.CreateFmt(SErrUnknownInputAdaptor,[AAdaptorName]);
  1154. end;
  1155. function TFPCustomWebDataProviderManager.GetInputAdaptor(
  1156. const ADef: TWebInputAdaptorDef; AOwner: TComponent
  1157. ): TCustomWebdataInputAdaptor;
  1158. Var
  1159. O: TComponent;
  1160. begin
  1161. O:=AOwner;
  1162. If (O=Nil) then
  1163. O:=Self;
  1164. Result:=ADef.CreateInstance(AOwner);
  1165. end;
  1166. function TFPCustomWebDataProviderManager.GetInputAdaptor(
  1167. const AAdaptorName: String; AOwner: TComponent): TCustomWebdataInputAdaptor;
  1168. begin
  1169. Result:=GetInputAdaptor(GetInputAdaptorDefByName(AAdaptorName),Aowner);
  1170. end;
  1171. function TFPCustomWebDataProviderManager.RegisterDataProducer(
  1172. const AProducerName: String; AClass: TCustomHTTPDataContentProducerClass
  1173. ): THttpDataProducerDef;
  1174. begin
  1175. If IndexOfHttpDataProducerDef(AProducerName)<>-1 then
  1176. Raise EFPHTTPError.CreateFmt(SErrDuplicateHTTPDataProducer,[AProducerName]);
  1177. Result:=AddHttpDataProducerDef(AProducerName,AClass);
  1178. end;
  1179. procedure TFPCustomWebDataProviderManager.UnRegisterDataProducer(
  1180. const AProducerName: String);
  1181. Var
  1182. I : Integer;
  1183. begin
  1184. I:=IndexOfHttpDataProducerDef(AProducerName);
  1185. If (I<>-1) then
  1186. RemoveHttpDataProducerDef(I);
  1187. end;
  1188. function TFPCustomWebDataProviderManager.FindDataProducerDefByName(
  1189. const AProducerName: String): THttpDataProducerDef;
  1190. Var
  1191. I : Integer;
  1192. begin
  1193. I:=IndexOfHttpDataProducerDef(AProducerName);
  1194. If (I<>-1) then
  1195. Result:=GetHttpDataProducerDef(I)
  1196. else
  1197. Result:=Nil;
  1198. end;
  1199. function TFPCustomWebDataProviderManager.GetDataProducerDefByName(
  1200. const AProducerName: String): THttpDataProducerDef;
  1201. begin
  1202. Result:=FindDataProducerDefByName(AProducerName);
  1203. If (Result=Nil) then
  1204. Raise EFPHTTPError.CreateFmt(SErrUnknownHTTPDataProducer,[AProducerName]);
  1205. end;
  1206. function TFPCustomWebDataProviderManager.GetDataProducer(
  1207. ADef: THttpDataProducerDef; AOwner: TComponent
  1208. ): TCustomHTTPDataContentProducer;
  1209. Var
  1210. O : TComponent;
  1211. begin
  1212. O:=AOwner;
  1213. If (O=Nil) then
  1214. O:=Self;
  1215. Result:=ADef.CreateInstance(Aowner);
  1216. end;
  1217. function TFPCustomWebDataProviderManager.GetDataProducer(
  1218. const AProducerName: String; AOwner : TComponent): TCustomHTTPDataContentProducer;
  1219. begin
  1220. Result:=GetDataProducer(GetDataProducerDefByName(AProducerName),Aowner);
  1221. end;
  1222. function TFPCustomWebDataProviderManager.GetProvider(
  1223. const ADef: TWebDataProviderDef; AOwner: TComponent; Out AContainer : TComponent): TFPCustomWebDataProvider;
  1224. Var
  1225. O : TComponent;
  1226. begin
  1227. If AOwner<>Nil then
  1228. O:=Self
  1229. else
  1230. O:=AOwner;
  1231. Result:=ADef.CreateInstance(O,AContainer);
  1232. end;
  1233. { TFPWebDataProviderManager }
  1234. constructor TFPWebDataProviderManager.Create(AOwner: TComponent);
  1235. begin
  1236. inherited Create(AOwner);
  1237. FProviderDefs:=TWebDataProviderDefs.Create(TWebDataProviderDef);
  1238. FAdaptorDefs:=TWebInputAdaptorDefs.Create(TWebInputAdaptorDef);
  1239. FProducerDefs:=THttpDataProducerDefs.Create(THttpDataProducerDef);
  1240. end;
  1241. destructor TFPWebDataProviderManager.Destroy;
  1242. begin
  1243. FreeAndNil(FProviderDefs);
  1244. FreeAndNil(FAdaptorDefs);
  1245. FreeAndNil(FProducerDefs);
  1246. inherited Destroy;
  1247. end;
  1248. procedure TFPWebDataProviderManager.RemoveProviderDef(const Index: Integer);
  1249. begin
  1250. FProviderDefs.Delete(Index);
  1251. end;
  1252. function TFPWebDataProviderManager.AddProviderDef(const AProviderName: String
  1253. ): TWebDataProviderDef;
  1254. begin
  1255. Result:=FProviderDefs.AddProvider(AProviderName);
  1256. end;
  1257. function TFPWebDataProviderManager.IndexOfProviderDef(const AProviderName: String
  1258. ): Integer;
  1259. begin
  1260. {$ifdef wmdebug}Senddebug('Entering indexofproviderdef : '+AProviderName);{$endif}
  1261. {$ifdef wmdebug}Senddebug(Format('Providerdefs assigned: %d ',[Ord(Assigned(FProviderDefs))]));{$endif}
  1262. Result:=FProviderDefs.IndexOfProvider(AProviderName);
  1263. {$ifdef wmdebug}Senddebug('Exitining indexofproviderdef: '+IntToStr(result));{$endif}
  1264. end;
  1265. function TFPWebDataProviderManager.GetProviderDef(Index: Integer
  1266. ): TWebDataProviderDef;
  1267. begin
  1268. Result:=FProviderDefs[Index];
  1269. end;
  1270. function TFPWebDataProviderManager.GetProviderDefCount: Integer;
  1271. begin
  1272. Result:=FProviderDefs.Count;
  1273. end;
  1274. function TFPWebDataProviderManager.AddInputAdaptorDef(
  1275. const AAdaptorName: String; AClass: TCustomWebdataInputAdaptorClass
  1276. ): TWebInputAdaptorDef;
  1277. begin
  1278. Result:=FAdaptorDefs.AddAdaptor(AAdaptorName,AClass);
  1279. end;
  1280. function TFPWebDataProviderManager.IndexOfInputAdaptorDef(
  1281. const AAdaptorName: String): Integer;
  1282. begin
  1283. Result:=FAdaptorDefs.IndexOfAdaptor(AAdaptorName);
  1284. end;
  1285. Procedure TFPWebDataProviderManager.RemoveInputAdaptorDef(Index : integer);
  1286. begin
  1287. If (Index<>-1) then
  1288. FAdaptorDefs.Delete(Index);
  1289. end;
  1290. function TFPWebDataProviderManager.GetInputAdaptorDef(Index: Integer
  1291. ): TWebInputAdaptorDef;
  1292. begin
  1293. Result:=FAdaptorDefs[Index];
  1294. end;
  1295. function TFPWebDataProviderManager.GetInputAdaptorDefCount: Integer;
  1296. begin
  1297. Result:=FAdaptorDefs.Count;
  1298. end;
  1299. function TFPWebDataProviderManager.AddHttpDataProducerDef(
  1300. const AProducerName: String; AClass: TCustomHTTPDataContentProducerClass
  1301. ): THttpDataProducerDef;
  1302. begin
  1303. Result:=FProducerDefs.AddProducer(AProducerName,AClass);
  1304. end;
  1305. function TFPWebDataProviderManager.IndexOfHttpDataProducerDef(
  1306. const AProducerName: String): Integer;
  1307. begin
  1308. Result:=FProducerDefs.IndexOfProducer(AProducerName);
  1309. end;
  1310. procedure TFPWebDataProviderManager.RemoveHttpDataProducerDef(Index: Integer);
  1311. begin
  1312. FProducerDefs.Delete(Index);
  1313. end;
  1314. function TFPWebDataProviderManager.GetHttpDataProducerDef(Index: Integer
  1315. ): THttpDataProducerDef;
  1316. begin
  1317. Result:=FProducerDefs[Index];
  1318. end;
  1319. function TFPWebDataProviderManager.GetHttpDataProducerDefCount: Integer;
  1320. begin
  1321. Result:=FProducerDefs.Count;
  1322. end;
  1323. { TFPCustomWebProviderDataModule }
  1324. procedure TFPCustomWebProviderDataModule.ReadWebData(AProvider: TFPCustomWebDataProvider
  1325. );
  1326. Var
  1327. B : Boolean;
  1328. begin
  1329. B:=False;
  1330. If Assigned(FBeforeRead) then
  1331. FBeforeRead(Self,AProvider,B);
  1332. if Not B then
  1333. DoReadWebData(AProvider);
  1334. If Assigned(FAfterRead) then
  1335. FAfterRead(Self,AProvider);
  1336. end;
  1337. procedure TFPCustomWebProviderDataModule.InsertWebData(
  1338. AProvider: TFPCustomWebDataProvider);
  1339. Var
  1340. B : Boolean;
  1341. begin
  1342. B:=False;
  1343. If Assigned(FBeforeInsert) then
  1344. FBeforeInsert(Self,AProvider,B);
  1345. if Not B then
  1346. DoInsertWebData(AProvider);
  1347. If Assigned(FAfterInsert) then
  1348. FAfterInsert(Self,AProvider);
  1349. end;
  1350. procedure TFPCustomWebProviderDataModule.SetContentProducer(
  1351. const AValue: TCustomHTTPDataContentProducer);
  1352. begin
  1353. if FContentProducer=AValue then exit;
  1354. FContentProducer:=AValue;
  1355. end;
  1356. procedure TFPCustomWebProviderDataModule.SetInputAdaptor(
  1357. const AValue: TCustomWebdataInputAdaptor);
  1358. begin
  1359. if FInputAdaptor=AValue then exit;
  1360. FInputAdaptor:=AValue;
  1361. end;
  1362. procedure TFPCustomWebProviderDataModule.UpdateWebData(
  1363. AProvider: TFPCustomWebDataProvider);
  1364. Var
  1365. B : Boolean;
  1366. begin
  1367. B:=False;
  1368. If Assigned(FBeforeUpdate) then
  1369. FBeforeUpdate(Self,AProvider,B);
  1370. if Not B then
  1371. DoUpdateWebData(AProvider);
  1372. If Assigned(FAfterUpdate) then
  1373. FAfterUpdate(Self,AProvider);
  1374. end;
  1375. procedure TFPCustomWebProviderDataModule.DeleteWebData(
  1376. AProvider: TFPCustomWebDataProvider);
  1377. Var
  1378. B : Boolean;
  1379. begin
  1380. B:=False;
  1381. If Assigned(FBeforeDelete) then
  1382. FBeforeDelete(Self,AProvider,B);
  1383. if Not B then
  1384. DoDeleteWebData(AProvider);
  1385. If Assigned(FAfterDelete) then
  1386. FAfterDelete(Self,AProvider);
  1387. end;
  1388. Function TFPCustomWebProviderDataModule.GetAdaptor : TCustomWebdataInputAdaptor;
  1389. begin
  1390. Result:=Self.InputAdaptor;
  1391. If Assigned(FOnGetInputAdaptor) then
  1392. FOnGetInputAdaptor(Self,Result);
  1393. end;
  1394. function TFPCustomWebProviderDataModule.GetContentProducer: TCustomHTTPDataContentProducer;
  1395. begin
  1396. Result:=FContentProducer;
  1397. If Assigned(FOnGetContentProducer) then
  1398. FOnGetContentProducer(Self,Result);
  1399. end;
  1400. procedure TFPCustomWebProviderDataModule.ProduceContent(
  1401. AProvider: TFPCustomWebDataProvider);
  1402. Var
  1403. A : TCustomWebdataInputAdaptor;
  1404. C : TCustomHTTPDataContentProducer;
  1405. Handled : boolean;
  1406. M : TmemoryStream;
  1407. begin
  1408. A:=GetAdaptor;
  1409. A.Request:=Self.Request;
  1410. AProvider.Adaptor:=A;
  1411. C:=GetContentProducer;
  1412. C.Adaptor:=A;
  1413. C.Provider:=AProvider;
  1414. M:=TMemoryStream.Create;
  1415. try
  1416. Handled:=True;
  1417. C.GetContent(Request,M,Handled);
  1418. If Handled then
  1419. begin
  1420. M.Position:=0;
  1421. If Assigned(FOnContent) then
  1422. FOnContent(Self,M);
  1423. Response.ContentType:=C.DataContentType;
  1424. Response.ContentStream:=M;
  1425. Response.SendResponse;
  1426. Response.ContentStream:=Nil;
  1427. end
  1428. else
  1429. Raise EFPHTTPError.CreateFmt(SErrContentProviderRequest,[C.Name]);
  1430. finally
  1431. M.Free;
  1432. end;
  1433. end;
  1434. procedure TFPCustomWebProviderDataModule.DoReadWebData(
  1435. AProvider: TFPCustomWebDataProvider);
  1436. begin
  1437. ProduceContent(AProvider);
  1438. end;
  1439. procedure TFPCustomWebProviderDataModule.DoInsertWebData(
  1440. AProvider: TFPCustomWebDataProvider);
  1441. begin
  1442. ProduceContent(AProvider);
  1443. end;
  1444. procedure TFPCustomWebProviderDataModule.DoUpdateWebData(
  1445. AProvider: TFPCustomWebDataProvider);
  1446. begin
  1447. ProduceContent(AProvider);
  1448. end;
  1449. procedure TFPCustomWebProviderDataModule.DoDeleteWebData(
  1450. AProvider: TFPCustomWebDataProvider);
  1451. begin
  1452. ProduceContent(AProvider);
  1453. end;
  1454. Constructor TFPCustomWebProviderDataModule.CreateNew(AOwner : TComponent; CreateMode : Integer);
  1455. begin
  1456. inherited;
  1457. FUseProviderManager:=True;
  1458. end;
  1459. Function TFPCustomWebProviderDataModule.GetProvider(Const AProviderName : String; Out AContainer : TComponent) : TFPCustomWebDataProvider;
  1460. Var
  1461. C : TComponent;
  1462. ADef : TWebDataProviderDef;
  1463. P : TFPCustomWebDataProvider;
  1464. begin
  1465. Result:=Nil;
  1466. AContainer:=Nil;
  1467. If Assigned(FOnGetProvider) then
  1468. begin
  1469. FOngetProvider(Self,AProviderName,Result);
  1470. If Assigned(Result) then
  1471. begin
  1472. AContainer:=Nil;
  1473. Exit;
  1474. end;
  1475. end;
  1476. P:=Nil;
  1477. C:=FindComponent(AProviderName);
  1478. {$ifdef wmdebug}SendDebug(Format('Searching provider "%s" 1 : %d ',[AProvidername,Ord(Assigned(C))]));{$endif}
  1479. If (C<>Nil) and (C is TFPCustomWebDataProvider) then
  1480. P:=TFPCustomWebDataProvider(C)
  1481. else if UseProviderManager then
  1482. begin
  1483. {$ifdef wmdebug}SendDebug(Format('Searching providerdef "%s" 1 : %d ',[AProvidername,Ord(Assigned(C))]));{$endif}
  1484. ADef:=WebDataProviderManager.FindProviderDefByName(AProviderName);
  1485. If (ADef<>Nil) then
  1486. begin
  1487. {$ifdef wmdebug}SendDebug(Format('Found providerdef "%s" 1 : %d ',[AProvidername,Ord(Assigned(C))]));{$endif}
  1488. P:=WebDataProviderManager.GetProvider(ADef,Self,AContainer);
  1489. end
  1490. else
  1491. P:=Nil;
  1492. end;
  1493. {$ifdef wmdebug}SendDebug(Format('Searching provider "%s" 2 : %d ',[AProvidername,Ord(Assigned(C))]));{$endif}
  1494. Result:=P;
  1495. If (Result=Nil) then
  1496. Raise EFPHTTPError.CreateFmt(SErrUnknownWebDataProvider,[AProviderName]);
  1497. end;
  1498. procedure TFPCustomWebProviderDataModule.HandleRequest(ARequest: TRequest;
  1499. AResponse: TResponse);
  1500. Var
  1501. ProviderName : String;
  1502. AProvider : TFPCustomWebDataProvider;
  1503. A : TCustomWebdataInputAdaptor;
  1504. Wa : TWebDataAction;
  1505. AContainer : TComponent;
  1506. begin
  1507. FRequest:=ARequest;
  1508. FResponse:=AResponse;
  1509. try
  1510. {$ifdef wmdebug}SendDebug('Checking session');{$endif}
  1511. CheckSession(ARequest);
  1512. {$ifdef wmdebug}SendDebug('Init session');{$endif}
  1513. InitSession(AResponse);
  1514. {$ifdef wmdebug}SendDebug('Getting providername');{$endif}
  1515. ProviderName:=Request.GetNextPathInfo;
  1516. {$ifdef wmdebug}SendDebug('Handlerequest, providername : '+Providername);{$endif}
  1517. AProvider:=GetProvider(ProviderName,AContainer);
  1518. try
  1519. If not CORS.HandleRequest(aRequest,aResponse,[hcDetect,hcSend]) then
  1520. begin
  1521. A:=GetAdaptor;
  1522. A.Request:=ARequest;
  1523. A.Reset; // Force. for wmKind=pooled, fastcgi, request can be the same.
  1524. Wa:=A.GetAction;
  1525. Case WA of
  1526. wdaUnknown : Raise EFPHTTPError.CreateFmt(SErrUnknownProviderAction,[ProviderName]);
  1527. wdaRead : ReadWebData(AProvider);
  1528. wdaUpdate : UpdateWebData(AProvider);
  1529. wdaInsert : InsertWebdata(AProvider);
  1530. wdaDelete : DeleteWebData(AProvider);
  1531. end;
  1532. UpdateSession(AResponse);
  1533. end;
  1534. finally
  1535. If (AContainer=Nil) then
  1536. begin
  1537. If (AProvider.Owner<>Self) then
  1538. AProvider.Free;
  1539. end
  1540. else
  1541. AContainer.Free;
  1542. end;
  1543. finally
  1544. FRequest:=Nil;
  1545. FResponse:=Nil;
  1546. end;
  1547. end;
  1548. { TWebInputAdaptorDef }
  1549. procedure TWebInputAdaptorDef.SetName(const AValue: String);
  1550. begin
  1551. if FName=AValue then exit;
  1552. FName:=AValue;
  1553. end;
  1554. function TWebInputAdaptorDef.CreateInstance(AOwner: TComponent
  1555. ): TCustomWebdataInputAdaptor;
  1556. begin
  1557. Result:=FClass.Create(AOwner);
  1558. end;
  1559. { TWebInputAdaptorDefs }
  1560. function TWebInputAdaptorDefs.GetD(Index : Integer): TWebInputAdaptorDef;
  1561. begin
  1562. Result:=TWebInputAdaptorDef(Items[Index]);
  1563. end;
  1564. procedure TWebInputAdaptorDefs.SetD(Index : Integer;
  1565. const AValue: TWebInputAdaptorDef);
  1566. begin
  1567. Items[Index]:=AValue;
  1568. end;
  1569. function TWebInputAdaptorDefs.IndexOfAdaptor(const AAdaptorName: String
  1570. ): Integer;
  1571. begin
  1572. Result:=Count-1;
  1573. While (Result>=0) and (CompareText(GetD(Result).Name,AAdaptorName)<>0) do
  1574. Dec(Result);
  1575. end;
  1576. function TWebInputAdaptorDefs.AddAdaptor(const AAdaptorName: String;
  1577. AClass: TCustomWebdataInputAdaptorClass): TWebInputAdaptorDef;
  1578. Var
  1579. I : Integer;
  1580. begin
  1581. I:=IndexOfAdaptor(AAdaptorName);
  1582. If (I=-1) then
  1583. begin
  1584. Result:=Add as TWebInputAdaptorDef;
  1585. Result.FName:=AAdaptorName;
  1586. Result.FClass:=AClass;
  1587. end
  1588. else
  1589. Raise EFPHTTPError.CreateFmt(SErrDuplicateAdaptor,[AAdaptorName]);
  1590. end;
  1591. { THttpDataProducerDef }
  1592. procedure THttpDataProducerDef.SetName(const AValue: String);
  1593. begin
  1594. If AValue=FName then exit;
  1595. If (AValue<>'') and Assigned(Collection) and (Collection is THttpDataProducerDefs) then
  1596. if THttpDataProducerDefs(Collection).IndexOfProducer(AValue)<>-1 then
  1597. Raise EFPHTTPError.CreateFmt(SErrDuplicateHTTPDataProducer,[AValue]);
  1598. FName:=Avalue;
  1599. end;
  1600. function THttpDataProducerDef.CreateInstance(AOwner: TComponent
  1601. ): TCustomHTTPDataContentProducer;
  1602. begin
  1603. Result:=FClass.Create(AOwner);
  1604. end;
  1605. { THttpDataProducerDefs }
  1606. function THttpDataProducerDefs.GetD(Index: Integer): THttpDataProducerDef;
  1607. begin
  1608. Result:=THttpDataProducerDef(Items[Index]);
  1609. end;
  1610. procedure THttpDataProducerDefs.SetD(Index: Integer;
  1611. const AValue: THttpDataProducerDef);
  1612. begin
  1613. Items[Index]:=AValue;
  1614. end;
  1615. function THttpDataProducerDefs.IndexOfProducer(const AProducerName: String
  1616. ): Integer;
  1617. begin
  1618. Result:=Count-1;
  1619. While (Result>=0) and (CompareText(GetD(Result).Name,AProducerName)<>0) do
  1620. Dec(Result);
  1621. end;
  1622. function THttpDataProducerDefs.AddProducer(const AProducerName: String;
  1623. AClass: TCustomHTTPDataContentProducerClass): THttpDataProducerDef;
  1624. Var
  1625. I : Integer;
  1626. begin
  1627. I:=IndexOfProducer(AProducerName);
  1628. If (I=-1) then
  1629. begin
  1630. Result:=Add as THttpDataProducerDef;
  1631. Result.FName:=AProducerName;
  1632. Result.FClass:=AClass;
  1633. end
  1634. else
  1635. Raise EFPHTTPError.CreateFmt(SErrDuplicateHTTPDataProducer,[AProducerName]);
  1636. end;
  1637. { TWebdataInputAdaptor }
  1638. procedure TWebdataInputAdaptor.SetInputFormat(const AValue: String);
  1639. begin
  1640. if FInputFormat=AValue then exit;
  1641. If Assigned(FProxy) then
  1642. ClearProxy;
  1643. FInputFormat:=AValue;
  1644. end;
  1645. procedure TWebdataInputAdaptor.ClearProxy;
  1646. begin
  1647. FreeAndNil(FProxy);
  1648. end;
  1649. procedure TWebdataInputAdaptor.CheckProxy;
  1650. begin
  1651. If (FProxy=Nil) then
  1652. FProxy:=CreateProxy;
  1653. end;
  1654. function TWebdataInputAdaptor.CreateProxy: TCustomWebdataInputAdaptor;
  1655. begin
  1656. Result:=WebDataProviderManager.GetInputAdaptor(FInputFormat);
  1657. end;
  1658. function TWebdataInputAdaptor.GetActionFromRequest: TWebDataAction;
  1659. begin
  1660. CheckProxy;
  1661. Result:=FProxy.GetActionFromRequest;
  1662. end;
  1663. destructor TWebdataInputAdaptor.Destroy;
  1664. begin
  1665. ClearProxy;
  1666. Inherited;
  1667. end;
  1668. function TWebdataInputAdaptor.GetNextBatch: Boolean;
  1669. begin
  1670. CheckProxy;
  1671. Result:=FProxy.GetNextBatch;
  1672. end;
  1673. function TWebdataInputAdaptor.TryParamValue(const AParamName: String; out
  1674. AValue: String): Boolean;
  1675. begin
  1676. CheckProxy;
  1677. Result:=FProxy.TryParamValue(AParamName, AValue);
  1678. end;
  1679. function TWebdataInputAdaptor.TryFieldValue(const AFieldName: String; out
  1680. AValue: String): Boolean;
  1681. begin
  1682. CheckProxy;
  1683. Result:=FProxy.TryFieldValue(AFieldName, AValue);
  1684. end;
  1685. { THTTPDataContentProducer }
  1686. procedure THTTPDataContentProducer.SetOutputFormat(const AValue: String);
  1687. begin
  1688. if FOutputFormat=AValue then exit;
  1689. If Assigned(FProxy) then
  1690. ClearProxy;
  1691. FOutputFormat:=AValue;
  1692. end;
  1693. procedure THTTPDataContentProducer.ClearProxy;
  1694. begin
  1695. FreeAndNil(FProxy);
  1696. end;
  1697. procedure THTTPDataContentProducer.CheckProxy;
  1698. begin
  1699. If not Assigned(FProxy) then
  1700. begin
  1701. FProxy:=CreateProxy;
  1702. end;
  1703. end;
  1704. function THTTPDataContentProducer.CreateProxy: TCustomHTTPDataContentProducer;
  1705. begin
  1706. Result:=WebDataProviderManager.GetDataProducer(FOutputFormat,Self);
  1707. ConfigureProxy(Result);
  1708. end;
  1709. Procedure THTTPDataContentProducer.ConfigureProxy(AProxy : TCustomHTTPDataContentProducer);
  1710. begin
  1711. AProxy.PageSize:=Self.PageSize;
  1712. AProxy.PageStart:=Self.PageStart;
  1713. AProxy.MetaData:=Self.MetaData;
  1714. AProxy.SortField:=Self.SortField;
  1715. AProxy.SortDescending:=Self.SortDescending;
  1716. AProxy.AllowPageSize:=Self.AllowPageSize;
  1717. If Assigned(FOnConfigure) then
  1718. FOnConfigure(AProxy);
  1719. end;
  1720. destructor THTTPDataContentProducer.destroy;
  1721. begin
  1722. ClearProxy;
  1723. inherited destroy;
  1724. end;
  1725. initialization
  1726. finalization
  1727. FreeAndNil(AWebDataProviderManager);
  1728. end.