Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 328 lines (275 sloc) 9.836 kB
7dee2ab importing articles and code
Alex authored
1 //
2 // RowFormatter.cpp
3 //
4 // $Id: //poco/Main/Data/samples/RecordSet/src/RowFormatter.cpp#2 $
5 //
6 // This a sample demonstrating the Data library recordset row formatting
7 // and streaming capabilities that was used at the 2012 Silicon Valley
8 // Code Camp conference.
9 //
10 // Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
11 // and Contributors.
12 //
13 // Permission is hereby granted, free of charge, to any person or organization
14 // obtaining a copy of the software and accompanying documentation covered by
15 // this license (the "Software") to use, reproduce, display, distribute,
16 // execute, and transmit the Software, and to prepare derivative works of the
17 // Software, and to permit third-parties to whom the Software is furnished to
18 // do so, all subject to the following:
19 //
20 // The copyright notices in the Software and this entire statement, including
21 // the above license grant, this restriction and the following disclaimer,
22 // must be included in all copies of the Software, in whole or in part, and
23 // all derivative works of the Software, unless such copies or derivative
24 // works are solely in the form of machine-executable object code generated by
25 // a source language processor.
26 //
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
30 // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
31 // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
32 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
33 // DEALINGS IN THE SOFTWARE.
34
35
36 #include "Poco/SharedPtr.h"
37 #include "Poco/URI.h"
38 #include "Poco/Path.h"
39 #include "Poco/File.h"
40 #include "Poco/FileStream.h"
41 #include "Poco/Data/SessionFactory.h"
42 #include "Poco/Data/Session.h"
43 #include "Poco/Data/Statement.h"
44 #include "Poco/Data/RecordSet.h"
45 #include "Poco/Data/RowFormatter.h"
46 #include "Poco/Data/SQLite/Connector.h"
47 #include "Poco/Net/HTTPServer.h"
48 #include "Poco/Net/HTTPRequestHandler.h"
49 #include "Poco/Net/HTTPRequestHandlerFactory.h"
50 #include "Poco/Net/HTTPServerParams.h"
51 #include "Poco/Net/HTTPServerRequest.h"
52 #include "Poco/Net/HTTPServerResponse.h"
53 #include "Poco/Net/HTTPResponse.h"
54 #include "Poco/Net/HTTPServerParams.h"
55 #include "Poco/Net/ServerSocket.h"
56 #include <iostream>
57
58
59 using namespace Poco::Data::Keywords;
60 using Poco::URI;
61 using Poco::Path;
62 using Poco::File;
63 using Poco::FileInputStream;
64 using Poco::Data::Session;
65 using Poco::Data::Statement;
66 using Poco::Data::RecordSet;
67 using Poco::Data::RowFormatter;
68 using Poco::Net::ServerSocket;
69 using Poco::Net::HTTPRequestHandler;
70 using Poco::Net::HTTPRequestHandlerFactory;
71 using Poco::Net::HTTPServer;
72 using Poco::Net::HTTPServerRequest;
73 using Poco::Net::HTTPServerResponse;
74 using Poco::Net::HTTPServerParams;
75 using Poco::Net::HTTPResponse;
76
77
78 #define ROOT_DIR "C:\\trunk\\Data\\samples\\RowFormatter\\bin\\"
79
80
81 std::string getSQL(const std::string& file = ROOT_DIR"simpsons.sql")
82 {
83 Poco::FileInputStream fis(file);
84 std::string read, tmp;
85 while (!fis.eof()) { fis >> tmp; tmp += ' '; read += tmp; }
86 return read;
87 }
88
89
90 bool fileExists(const HTTPServerRequest& request, std::string& fullPath)
91 {
92 std::string root = ROOT_DIR;
93 URI uri(request.getURI());
94 std::string path = uri.getPath();
95 Poco::Path requestPath(path, Poco::Path::PATH_UNIX);
96 Poco::Path localPath(root);
97 localPath.makeDirectory();
98 for (int i = 0; i < requestPath.depth(); i++)
99 localPath.pushDirectory(requestPath[i]);
100
101 localPath.setFileName(requestPath.getFileName());
102 Poco::File localFile(localPath.toString());
103 std::cout << "Path: " << localPath.toString() << std::endl;
104 if (localFile.exists())
105 {
106 fullPath = localPath.toString();
107 return true;
108 }
109
110 return false;
111 }
112
113
114 class NotFoundRequestHandler: public HTTPRequestHandler
115 {
116 public:
117 void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
118 {
119 response.setStatusAndReason(HTTPResponse::HTTP_NOT_FOUND);
120 response.send();
121 }
122 };
123
124
125 class FileRequestHandler: public HTTPRequestHandler
126 {
127 public:
128 FileRequestHandler(const std::string& file): _file(file) { }
129 void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
130 {
131 response.setChunkedTransferEncoding(true);
132 //response.setContentType("text/html");
133
134 Path path(_file);
135 if (File(path).exists())
136 {
137 std::string mime = "application/binary";
138 std::string ext = path.getExtension();
139 if (ext == "html" || ext == "htm" || ext == "js" || ext == "css" || ext == "xml")
140 mime = "text/" + ext;
141
142 response.sendFile(_file, mime);
143 }
144 else
145 {
146 response.setStatusAndReason(HTTPResponse::HTTP_NOT_FOUND);
147 response.send();
148 }
149 }
150 private:
151 std::string _file;
152 };
153
154
155 class HTMLTableFormatter : public RowFormatter
156 {
157 public:
158 HTMLTableFormatter()
159 {
160 std::ostringstream os;
161 os << "<TABLE border=\"1\" cellspacing=\"0\">" << std::endl;
162 setPrefix(os.str());
163
164 os.str("");
165 os << "</TABLE>" << std::endl;
166 setPostfix(os.str());
167 }
168
169 std::string& formatNames(const NameVecPtr pNames, std::string& formattedNames)
170 {
171 std::ostringstream str;
172
173 str << "\t<TR>" << std::endl;
174 NameVec::const_iterator it = pNames->begin();
175 NameVec::const_iterator end = pNames->end();
176 for (; it != end; ++it) str << "\t\t<TH align=\"center\">" << *it << "</TH>" << std::endl;
177 str << "\t</TR>" << std::endl;
178
179 return formattedNames = str.str();
180 }
181
182 std::string& formatValues(const ValueVec& vals, std::string& formattedValues)
183 {
184 std::ostringstream str;
185
186 str << "\t<TR>" << std::endl;
187 ValueVec::const_iterator it = vals.begin();
188 ValueVec::const_iterator end = vals.end();
189 for (; it != end; ++it)
190 {
191 if (it->isNumeric())
192 str << "\t\t<TD align=\"right\">";
193 else
194 str << "\t\t<TD align=\"left\">";
195
196 str << it->convert<std::string>() << "</TD>" << std::endl;
197 }
198 str << "\t</TR>" << std::endl;
199
200 return formattedValues = str.str();
201 }
202 };
203
204
205 class XMLFormatter : public RowFormatter
206 {
207 public:
208 XMLFormatter() : _pNames(0)
209 {
210 std::ostringstream os;
211 os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl << "<Items>" << std::endl;
212 setPrefix(os.str());
213
214 os.str("");
215 os << "</Items>" << std::endl;
216 setPostfix(os.str());
217 }
218
219 std::string& formatNames(const NameVecPtr pNames, std::string& formattedNames)
220 {
221 _pNames = pNames;
222 return formattedNames;
223 }
224
225 std::string& formatValues(const ValueVec& vals, std::string& formattedValues)
226 {
227 if (!_pNames) return formattedValues;
228
229 std::ostringstream str;
230
231 str << "\t<Item>" << std::endl;
232 ValueVec::const_iterator it = vals.begin();
233 ValueVec::const_iterator end = vals.end();
234 NameVec::const_iterator nIt = _pNames->begin();
235 for (; it != end; ++it, ++nIt)
236 {
237 str << "\t\t<" << *nIt
238 << '>' << it->convert<std::string>()
239 << "</" << *nIt << '>' << std::endl;
240 }
241 str << "\t</Item>" << std::endl;
242
243 return formattedValues = str.str();
244 }
245 private:
246 NameVecPtr _pNames;
247 };
248
249
250 class DataRequestHandler: public HTTPRequestHandler
251 {
252 public:
253 void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
254 {
255 response.setChunkedTransferEncoding(true);
256
257 URI uri(request.getURI());
258 std::string path = uri.getPath();
259 std::string sql = getSQL();
260 std:: cout << "Executing;[" << sql << ']' << std::endl;
261 if (path == "/html")
262 {
263 response.setContentType("text/html");
264 response.send() << RecordSet(Session("SQLite", "simpsons.db"), sql, new HTMLTableFormatter);
265 }
266 else if (path == "/xml")
267 {
268 response.setContentType("text/xml");
269 response.send() << RecordSet(Session("SQLite", "simpsons.db"), sql, new XMLFormatter);
270 }
271 }
272 };
273
274
275 class DataRequestHandlerFactory: public HTTPRequestHandlerFactory
276 {
277 public:
278 HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& request)
279 {
280 std::string localPath;
281 std::string uriPath = URI(request.getURI()).getPath();
282
283 if (fileExists(request, localPath)) // request for a file
284 return new FileRequestHandler(localPath);
285 else if ((uriPath == "/html") || (uriPath == "/xml")) // request for data
286 return new DataRequestHandler();
287 else // sorry ...
288 return new NotFoundRequestHandler();
289 }
290 };
291
292
293 int main()
294 {
295 Poco::Data::SQLite::Connector::registerConnector();
296
297 HTTPServer srv(new DataRequestHandlerFactory, 8080);
298 srv.start();
299 getchar();
300 srv.stop();
301
302 return 0;
303 }
304
305 /* code to create table is below
306
307 ExtJS example is in bin/js/ext/examples/grid/simpsons.*
308
309 // drop sample table, if it exists
310 session << "DROP TABLE IF EXISTS Simpsons", now;
311
312 // (re)create table
313 session << "CREATE TABLE Simpsons (Name VARCHAR(30), Address VARCHAR, Age INTEGER(3))", now;
314
315 // insert some rows
316 session << "INSERT INTO Simpsons VALUES('Homer Simpson', 'Springfield', 42)", now;
317 session << "INSERT INTO Simpsons VALUES('Marge Simpson', 'Springfield', 38)", now;
318 session << "INSERT INTO Simpsons VALUES('Bart Simpson', 'Springfield', 12)", now;
319 session << "INSERT INTO Simpsons VALUES('Lisa Simpson', 'Springfield', 10)", now;
320
321 // Note: The code above is divided into individual steps for clarity purpose.
322 // The four lines can be reduced to the following single line of code:
323 std::cout << RecordSet(session, "SELECT * FROM Simpsons", new HTMLTableFormatter);
324
325 // simple formatting example (uses the default SimpleRowFormatter provided by framework)
326 std::cout << std::endl << "Simple formatting:" << std::endl << std::endl;
327 std::cout << RecordSet(session, "SELECT * FROM Simpsons");
328 */
Something went wrong with that request. Please try again.