fpwebdata.pp 61 KB

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