updated PageCompiler

This commit is contained in:
Guenter Obiltschnig 2012-10-13 10:07:17 +00:00
parent 045c23a9f6
commit 8f00fdb78a
7 changed files with 196 additions and 48 deletions

View File

@ -1,7 +1,7 @@
//
// File2Page.cpp
//
// $Id: //poco/1.4/PageCompiler/File2Page/src/File2Page.cpp#3 $
// $Id: //poco/1.4/PageCompiler/File2Page/src/File2Page.cpp#4 $
//
// An application that creates a Page Compiler source file from an
// ordinary file.
@ -88,46 +88,53 @@ protected:
Application::defineOptions(options);
options.addOption(
Option("help", "h", "display help information on command line arguments")
Option("help", "h", "Display help information on command line arguments.")
.required(false)
.repeatable(false)
.callback(OptionCallback<File2PageApp>(this, &File2PageApp::handleHelp)));
options.addOption(
Option("contentType", "t", "specify a content type")
Option("contentType", "t", "Specify a content type.")
.required(false)
.repeatable(false)
.argument("MIME-Type")
.callback(OptionCallback<File2PageApp>(this, &File2PageApp::handleContentType)));
options.addOption(
Option("contentLanguage", "l", "specify a content language")
Option("contentLanguage", "l", "Specify a content language.")
.required(false)
.repeatable(false)
.argument("language")
.callback(OptionCallback<File2PageApp>(this, &File2PageApp::handleContentLang)));
options.addOption(
Option("class", "c", "specify the handler class name")
Option("class", "c", "Specify the handler class name.")
.required(false)
.repeatable(false)
.argument("class-name")
.callback(OptionCallback<File2PageApp>(this, &File2PageApp::handleClassName)));
options.addOption(
Option("namespace", "n", "specify the handler class namespace name")
Option("namespace", "n", "Specify the handler class namespace name.")
.required(false)
.repeatable(false)
.argument("namespace-name")
.callback(OptionCallback<File2PageApp>(this, &File2PageApp::handleNamespace)));
options.addOption(
Option("output", "o", "specify the output file name")
Option("output", "o", "Specify the output file name.")
.required(false)
.repeatable(false)
.argument("path")
.callback(OptionCallback<File2PageApp>(this, &File2PageApp::handleOutput)));
}
options.addOption(
Option("path", "p", "Specify the server path of the file.")
.required(false)
.repeatable(false)
.argument("path")
.callback(OptionCallback<File2PageApp>(this, &File2PageApp::handlePath)));
}
void handleHelp(const std::string& name, const std::string& value)
{
@ -161,12 +168,18 @@ protected:
_output = value;
}
void handlePath(const std::string& name, const std::string& value)
{
_path = value;
}
void displayHelp()
{
HelpFormatter helpFormatter(options());
helpFormatter.setCommand(commandName());
helpFormatter.setUsage("OPTIONS");
helpFormatter.setHeader("Create a PageCompiler source file from a binary file.");
helpFormatter.setIndent(8);
helpFormatter.format(std::cout);
}
@ -200,8 +213,12 @@ protected:
}
ostr << " form=\"false\"\n"
<< " namespace=\"" << _namespace << "\"\n"
<< " class=\"" << _clazz << "\"\n"
<< " precondition=\"checkModified(request)\"%><%@"
<< " class=\"" << _clazz << "\"\n";
if (!_path.empty())
{
ostr << " path=\"" << _path << "\"\n";
}
ostr << " precondition=\"checkModified(request)\"%><%@"
<< " impl include=\"Poco/DateTime.h\"\n"
<< " include=\"Poco/DateTimeParser.h\"\n"
<< " include=\"Poco/DateTimeFormatter.h\"\n"
@ -292,6 +309,7 @@ private:
std::string _clazz;
std::string _namespace;
std::string _output;
std::string _path;
};

View File

@ -245,6 +245,28 @@ Allows you to specify whether the response is sent using chunked transfer encodi
Defaults to <[true]>.
Set the value to <[false]> to disable chunked transfer encoding.
!compressed
Enables or disables response body compression. If set to <[true]>, and the client supports
the "gzip" content encoding (indicated by the "Accept-Encoding" header),
the response body will be compressed using the "gzip" format and the
"Content-Encoding" header will be set accordingly.
Defaults to <[false]>. Cannot be enabled together with response buffering.
!compressionLevel
Specify the compression level, if response body compression is enabled.
Valid values are 1 (fastest) to 9 (best compression). Defaults to 1.
!buffered
Enables or disables response buffering. Response buffering is disabled by default.
Set to <[true]> to enable buffering, or to <[false]> to disable it.
If response buffering is enabled, everything written to the response stream
is actually written to a string stream (<[std::ostringstream]>).
Sending of the HTTP response back to the client is deferred to
when the page is complete.
!session (OSP only)
For use with the POCO Open Service Platform only.
@ -273,15 +295,6 @@ a new session will be created if the request does not contain a (valid) session
If set to <[false]> and there is no existing session that matches the session
cookie. the <[session]> variable will be null.
!buffered
Enables or disables response buffering. Response buffering is disabled by default.
Set to <[true]> to enable buffering, or to <[false]> to disable it.
If response buffering is enabled, everything written to the response stream
is actually written to a string stream (<[std::ostringstream]>).
Sending of the HTTP response back to the client is deferred to
when the page is complete.
!precondition
Allows to specify a C++ boolean expression which will be evaluated before processing
@ -295,6 +308,17 @@ Example:
<%@ page precondition="checkCredentials(request, response)" %>
----
!path
Specify a server path for the page. If specified, the generated handler class
will contain a public static <[const std::string]> member variable named <[PATH]>
containing the specified path.
Example:
<%@ page path="/index.html" %>
----
!!Implicit Objects
The following objects are available in the handler code.

View File

@ -1,7 +1,7 @@
//
// CodeWriter.cpp
//
// $Id: //poco/1.4/PageCompiler/src/CodeWriter.cpp#2 $
// $Id: //poco/1.4/PageCompiler/src/CodeWriter.cpp#3 $
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
@ -34,6 +34,7 @@
#include "Page.h"
#include "Poco/Path.h"
#include "Poco/StringTokenizer.h"
#include "Poco/String.h"
using Poco::Path;
@ -76,6 +77,10 @@ void CodeWriter::writeImpl(std::ostream& ostr, const std::string& headerFileName
{
ostr << "#include \"" << headerFileName << "\"\n";
writeImplIncludes(ostr);
if (_page.getBool("page.compressed", false))
{
ostr << "#include \"Poco/DeflatingStream.h\"\n";
}
if (_page.getBool("page.buffered", false))
{
ostr << "#include \"Poco/StreamCopier.h\"\n";
@ -90,6 +95,13 @@ void CodeWriter::writeImpl(std::ostream& ostr, const std::string& headerFileName
}
beginNamespace(ostr);
std::string path = _page.get("page.path", "");
if (!path.empty())
{
ostr << "\tconst std::string " << _class << "::PATH(\"" << path << "\");\n\n\n";
}
writeConstructor(ostr);
writeHandler(ostr);
writeFactory(ostr);
@ -132,7 +144,9 @@ void CodeWriter::beginGuard(std::ostream& ostr, const std::string& headerFileNam
{
Path p(headerFileName);
std::string guard(p.getBaseName());
Poco::translateInPlace(guard, ".-", "__");
guard += "_INCLUDED";
ostr << "#ifndef " << guard << "\n";
ostr << "#define " << guard << "\n";
ostr << "\n\n";
@ -143,6 +157,7 @@ void CodeWriter::endGuard(std::ostream& ostr, const std::string& headerFileName)
{
Path p(headerFileName);
std::string guard(p.getBaseName());
Poco::translateInPlace(guard, ".-", "__");
guard += "_INCLUDED";
ostr << "\n\n";
ostr << "#endif // " << guard << "\n";
@ -164,6 +179,13 @@ void CodeWriter::handlerClass(std::ostream& ostr, const std::string& base, const
}
ostr << "\tvoid handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response);\n";
writeHandlerMembers(ostr);
std::string path = _page.get("page.path", "");
if (!path.empty())
{
ostr << "\n\tstatic const std::string PATH;\n";
}
ostr << "};\n";
}
@ -313,6 +335,9 @@ void CodeWriter::writeResponse(std::ostream& ostr)
std::string contentLang(_page.get("page.contentLanguage", ""));
bool buffered(_page.getBool("page.buffered", false));
bool chunked(_page.getBool("page.chunked", !buffered));
bool compressed(_page.getBool("page.compressed", false));
if (buffered) compressed = false;
if (compressed) chunked = true;
if (chunked)
{
@ -325,6 +350,11 @@ void CodeWriter::writeResponse(std::ostream& ostr)
ostr << "\tif (request.has(\"Accept-Language\"))\n"
<< "\t\tresponse.set(\"Content-Language\", \"" << contentLang << "\");\n";
}
if (compressed)
{
ostr << "\tbool _compressResponse(request.hasToken(\"Accept-Encoding\", \"gzip\"));\n"
<< "\tif (_compressResponse) response.set(\"Content-Encoding\", \"gzip\");\n";
}
ostr << "\n";
}
@ -333,6 +363,10 @@ void CodeWriter::writeContent(std::ostream& ostr)
{
bool buffered(_page.getBool("page.buffered", false));
bool chunked(_page.getBool("page.chunked", !buffered));
bool compressed(_page.getBool("page.compressed", false));
int compressionLevel(_page.getInt("page.compressionLevel", 1));
if (buffered) compressed = false;
if (compressed) chunked = true;
if (buffered)
{
@ -344,6 +378,14 @@ void CodeWriter::writeContent(std::ostream& ostr)
}
ostr << "\tPoco::StreamCopier::copyStream(responseStream, response.send());\n";
}
else if (compressed)
{
ostr << "\tstd::ostream& _responseStream = response.send();\n"
<< "\tPoco::DeflatingOutputStream _gzipStream(_responseStream, Poco::DeflatingStreamBuf::STREAM_GZIP, " << compressionLevel << ");\n"
<< "\tstd::ostream& responseStream = _compressResponse ? _gzipStream : _responseStream;\n";
ostr << _page.handler().str();
ostr << "\tif (_compressResponse) _gzipStream.close();\n";
}
else
{
ostr << "\tstd::ostream& responseStream = response.send();\n";

View File

@ -1,7 +1,7 @@
//
// OSPCodeWriter.cpp
//
// $Id: //poco/1.4/PageCompiler/src/OSPCodeWriter.cpp#2 $
// $Id: //poco/1.4/PageCompiler/src/OSPCodeWriter.cpp#3 $
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
@ -64,6 +64,9 @@ void OSPCodeWriter::writeHandlerClass(std::ostream& ostr)
void OSPCodeWriter::writeHandlerMembers(std::ostream& ostr)
{
std::string base(page().get("page.baseClass", ""));
if (base.empty())
{
ostr << "\n";
ostr << "protected:\n";
ostr << "\tPoco::OSP::BundleContext::Ptr context() const\n";
@ -73,6 +76,7 @@ void OSPCodeWriter::writeHandlerMembers(std::ostream& ostr)
ostr << "\n";
ostr << "private:\n";
ostr << "\tPoco::OSP::BundleContext::Ptr _pContext;\n";
}
}
@ -97,9 +101,16 @@ void OSPCodeWriter::writeImplIncludes(std::ostream& ostr)
void OSPCodeWriter::writeConstructor(std::ostream& ostr)
{
std::string base(page().get("page.baseClass", "Poco::Net::HTTPRequestHandler"));
std::string base(page().get("page.baseClass", ""));
ostr << clazz() << "::" << clazz() << "(Poco::OSP::BundleContext::Ptr pContext):\n";
if (base.empty())
{
ostr << "\t_pContext(pContext)\n";
}
else
{
ostr << "\t" << base << "(pContext)\n";
}
ostr << "{\n}\n";
ostr << "\n\n";
}

View File

@ -1,7 +1,7 @@
//
// Page.cpp
//
// $Id: //poco/1.4/PageCompiler/src/Page.cpp#1 $
// $Id: //poco/1.4/PageCompiler/src/Page.cpp#2 $
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
@ -32,6 +32,7 @@
#include "Page.h"
#include "Poco/String.h"
#include "Poco/NumberParser.h"
Page::Page()
@ -55,3 +56,13 @@ bool Page::getBool(const std::string& property, bool deflt) const
}
else return deflt;
}
int Page::getInt(const std::string& property, int deflt) const
{
if (has(property))
{
return Poco::NumberParser::parse(get(property));
}
else return deflt;
}

View File

@ -1,7 +1,7 @@
//
// Page.h
//
// $Id: //poco/1.4/PageCompiler/src/Page.h#1 $
// $Id: //poco/1.4/PageCompiler/src/Page.h#2 $
//
// Copyright (c) 2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
@ -84,6 +84,9 @@ public:
///
/// Otherwise, the return value will be false.
int getInt(const std::string& property, int deflt = 0) const;
/// Returns the integer value of the given property.
private:
Page(const Page&);
Page& operator = (const Page&);

View File

@ -1,7 +1,7 @@
//
// PageCompiler.cpp
//
// $Id: //poco/1.4/PageCompiler/src/PageCompiler.cpp#3 $
// $Id: //poco/1.4/PageCompiler/src/PageCompiler.cpp#4 $
//
// A compiler that compiler HTML pages containing JSP directives into C++ classes.
//
@ -139,6 +139,13 @@ protected:
.argument("<prefix>")
.callback(OptionCallback<CompilerApp>(this, &CompilerApp::handleHeaderPrefix)));
options.addOption(
Option("base-file-name", "b", "Use <name> instead of the class name for the output file name.")
.required(false)
.repeatable(false)
.argument("<name>")
.callback(OptionCallback<CompilerApp>(this, &CompilerApp::handleBase)));
options.addOption(
Option("osp", "O", "Add factory class definition and implementation for use with the Open Service Platform.")
.required(false)
@ -191,6 +198,11 @@ protected:
_headerPrefix += '/';
}
void handleBase(const std::string& name, const std::string& value)
{
_base = value;
}
void handleOSP(const std::string& name, const std::string& value)
{
_generateOSPCode = true;
@ -259,15 +271,28 @@ protected:
return Application::EXIT_OK;
}
void compile(const std::string& path)
void parse(const std::string& path, Page& page, std::string& clazz)
{
Page page;
FileInputStream srcStream(path);
PageReader pageReader(page, path);
pageReader.emitLineDirectives(_emitLineDirectives);
pageReader.parse(srcStream);
Path p(path);
if (page.has("page.class"))
{
clazz = page.get("page.class");
}
else
{
clazz = p.getBaseName() + "Handler";
clazz[0] = Poco::Ascii::toUpper(clazz[0]);
}
}
void write(const std::string& path, const Page& page, const std::string& clazz)
{
Path p(path);
config().setString("inputFileName", p.getFileName());
config().setString("inputFilePath", p.toString());
@ -275,17 +300,10 @@ protected:
DateTime now;
config().setString("dateTime", DateTimeFormatter::format(now, DateTimeFormat::SORTABLE_FORMAT));
std::string clazz;
if (page.has("page.class"))
{
clazz = page.get("page.class");
p.setBaseName(clazz);
}
else
{
clazz = p.getBaseName() + "Handler";
clazz[0] = Poco::Ascii::toUpper(clazz[0]);
}
std::auto_ptr<CodeWriter> pCodeWriter(createCodeWriter(page, clazz));
@ -293,6 +311,12 @@ protected:
{
p = Path(_outputDir, p.getBaseName());
}
if (!_base.empty())
{
p.setBaseName(_base);
}
p.setExtension("cpp");
std::string implPath = p.toString();
std::string implFileName = p.getFileName();
@ -320,6 +344,20 @@ protected:
pCodeWriter->writeHeader(headerLEC, headerFileName);
}
void compile(const std::string& path)
{
Page page;
std::string clazz;
parse(path, page, clazz);
write(path, page, clazz);
FileInputStream srcStream(path);
PageReader pageReader(page, path);
pageReader.emitLineDirectives(_emitLineDirectives);
pageReader.parse(srcStream);
}
void writeFileHeader(std::ostream& ostr)
{
std::string fileHeader = config().getString("PageCompiler.fileHeader", "");
@ -348,6 +386,7 @@ private:
std::string _outputDir;
std::string _headerOutputDir;
std::string _headerPrefix;
std::string _base;
};