fpwebdata.pp 61 KB

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