Explorar o código

updated PageCompiler

Guenter Obiltschnig %!s(int64=13) %!d(string=hai) anos
pai
achega
8f00fdb78a

+ 28 - 10
PageCompiler/File2Page/src/File2Page.cpp

@@ -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;
 };
 
 

+ 33 - 9
PageCompiler/doc/PageCompilerUserGuide.page

@@ -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.

+ 44 - 2
PageCompiler/src/CodeWriter.cpp

@@ -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,7 +335,10 @@ 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)
 	{
 		ostr << "\tresponse.setChunkedTransferEncoding(true);\n";
@@ -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";

+ 23 - 12
PageCompiler/src/OSPCodeWriter.cpp

@@ -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,15 +64,19 @@ void OSPCodeWriter::writeHandlerClass(std::ostream& ostr)
 
 void OSPCodeWriter::writeHandlerMembers(std::ostream& ostr)
 {
-	ostr << "\n";
-	ostr << "protected:\n";
-	ostr << "\tPoco::OSP::BundleContext::Ptr context() const\n";
-	ostr << "\t{\n";
-	ostr << "\t\treturn _pContext;\n";
-	ostr << "\t}\n";
-	ostr << "\n";
-	ostr << "private:\n";
-	ostr << "\tPoco::OSP::BundleContext::Ptr _pContext;\n";
+	std::string base(page().get("page.baseClass", ""));
+	if (base.empty())
+	{
+		ostr << "\n";
+		ostr << "protected:\n";
+		ostr << "\tPoco::OSP::BundleContext::Ptr context() const\n";
+		ostr << "\t{\n";
+		ostr << "\t\treturn _pContext;\n";
+		ostr << "\t}\n";
+		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";
-	ostr << "\t_pContext(pContext)\n";
+	if (base.empty())
+	{
+		ostr << "\t_pContext(pContext)\n";
+	}
+	else
+	{
+		ostr << "\t" << base << "(pContext)\n";
+	}
 	ostr << "{\n}\n";
 	ostr << "\n\n";
 }

+ 12 - 1
PageCompiler/src/Page.cpp

@@ -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;
+}

+ 4 - 1
PageCompiler/src/Page.h

@@ -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&);

+ 52 - 13
PageCompiler/src/PageCompiler.cpp

@@ -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;	
@@ -205,7 +217,7 @@ protected:
 	{
 		_emitLineDirectives = false;
 	}
-
+	
 	void displayHelp()
 	{
 		HelpFormatter helpFormatter(options());
@@ -255,37 +267,43 @@ protected:
 		{
 			compile(*it);
 		}
-
+		
 		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);
-		config().setString("inputFileName", p.getFileName());
-		config().setString("inputFilePath", p.toString());
 		
-		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]);
 		}			
+	}
+	
+	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());
+		
+		DateTime now;
+		config().setString("dateTime", DateTimeFormatter::format(now, DateTimeFormat::SORTABLE_FORMAT));
+
+		if (page.has("page.class"))
+		{
+			p.setBaseName(clazz);
+		}
 
 		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();
@@ -319,6 +343,20 @@ protected:
 		writeFileHeader(headerLEC);
 		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)
 	{
@@ -348,6 +386,7 @@ private:
 	std::string _outputDir;
 	std::string _headerOutputDir;
 	std::string _headerPrefix;
+	std::string _base;
 };