From 965506c3e9ab1dca32c7be51c0271af78721c821 Mon Sep 17 00:00:00 2001 From: deva Date: Thu, 30 Jul 2009 07:23:42 +0000 Subject: Updated the example template to contain new tags/attributes. --- server/src/Makefile.am | 14 ++++ server/src/macrolist.cc | 15 ++++ server/src/server.cc | 28 +++---- server/src/templateheaderparser.cc | 142 +++++++++++++++++++++++++++++++ server/src/templateheaderparser.h | 62 ++++++++++++++ server/src/templatelist.cc | 167 +++++++++++++++++++++++++++++++++++++ server/src/templatelist.h | 72 ++++++++++++++++ server/src/templateparser.cc | 6 +- server/src/transactionparser.cc | 4 - server/xml/templates/example.xml | 14 +--- 10 files changed, 489 insertions(+), 35 deletions(-) create mode 100644 server/src/templateheaderparser.cc create mode 100644 server/src/templateheaderparser.h create mode 100644 server/src/templatelist.cc create mode 100644 server/src/templatelist.h diff --git a/server/src/Makefile.am b/server/src/Makefile.am index c7a2cfc..5516458 100644 --- a/server/src/Makefile.am +++ b/server/src/Makefile.am @@ -28,6 +28,8 @@ pracrod_SOURCES = \ resumeparser.cc \ saxparser.cc \ server.cc \ + templatelist.cc \ + templateheaderparser.cc \ templateparser.cc \ transactionparser.cc \ tcpsocket.cc \ @@ -89,6 +91,8 @@ EXTRA_DIST = \ resumeparser.h \ saxparser.h \ server.h \ + templatelist.h \ + templateheaderparser.h \ templateparser.h \ transactionparser.h \ tcpsocket.h \ @@ -102,6 +106,7 @@ EXTRA_DIST = \ ################ TESTFILES = \ + test_templatelist \ test_saxparser \ test_transactionparser \ test_versionstr \ @@ -134,6 +139,15 @@ test: $(TESTFILES) test_clean: rm -f $(TESTFILES) $(TESTLOGS) +TEST_TEMPLATELIST_FILES = \ + templatelist.cc \ + versionstr.cc \ + templateheaderparser.cc \ + $(PARSERFILES) \ + $(BASICFILES) +test_templatelist: $(TEST_TEMPLATELIST_FILES) + @../../tools/test $(TEST_TEMPLATELIST_FILES) $(PARSERFLAGS) $(BASICFLAGS) + TEST_SAXPARSER_FILES = \ saxparser.cc \ $(BASICFILES) diff --git a/server/src/macrolist.cc b/server/src/macrolist.cc index e8bc507..0e86a47 100644 --- a/server/src/macrolist.cc +++ b/server/src/macrolist.cc @@ -68,6 +68,21 @@ MacroList::MacroList(std::string macropath) (*this)[macro->attributes["name"]][VersionStr(macro->attributes["version"])] = *i; i++; } + + { + iterator i = begin(); + while(i != end()) { + MacroListItem::iterator j = i->second.begin(); + while(j != i->second.end()) { + PRACRO_DEBUG(macrolist, "%s - v%s file: %s\n", + i->first.c_str(), + ((std::string)j->first).c_str(), + j->second.c_str()); + j++; + } + i++; + } + } } std::string MacroList::getLatestVersion(std::string macro) throw(Exception) diff --git a/server/src/server.cc b/server/src/server.cc index 3ddb795..924ad84 100644 --- a/server/src/server.cc +++ b/server/src/server.cc @@ -55,6 +55,7 @@ #include "xml_encode_decode.h" #include "macrolist.h" +#include "templatelist.h" #include "versionstr.h" static std::string error_box(std::string message) @@ -112,7 +113,8 @@ static std::string handleRequest(Transaction *transaction, TCPSocket &pentominos_socket, Database &db, JournalWriter &journalwriter, - MacroList ¯olist) + MacroList ¯olist, + TemplateList &templatelist) { std::string answer; @@ -124,7 +126,7 @@ static std::string handleRequest(Transaction *transaction, request.macro.c_str(), request.course.c_str()); // Read and parse the template file. - TemplateParser tp(request.course); + TemplateParser tp(templatelist.getLatestVersion(request.course)); tp.parse(); Template *templ = tp.getTemplate(); @@ -254,7 +256,8 @@ static std::string handleTransaction(Transaction *transaction, TCPSocket &pentominos_socket, Database &db, JournalWriter &journalwriter, - MacroList ¯olist) + MacroList ¯olist, + TemplateList &templatelist) { std::string answer; answer += "\n"; @@ -268,7 +271,8 @@ static std::string handleTransaction(Transaction *transaction, } try { - answer += handleRequest(transaction, pentominos_socket, db, journalwriter, macrolist); + answer += handleRequest(transaction, pentominos_socket, db, journalwriter, + macrolist, templatelist); } catch( std::exception &e ) { PRACRO_ERR(server, "Request error: %s\n", e.what()); return error_box(xml_encode(e.what())); @@ -294,18 +298,7 @@ static void handleConnection(TCPSocket *socket) JournalWriter journalwriter(Conf::journal_commit_addr.c_str(), Conf::journal_commit_port); MacroList macrolist(Conf::xml_basedir + "/macros"); - MacroList::iterator i = macrolist.begin(); - while(i != macrolist.end()) { - MacroListItem::iterator j = i->second.begin(); - while(j != i->second.end()) { - PRACRO_DEBUG(server, "%s - v%s file: %s\n", - i->first.c_str(), - ((std::string)j->first).c_str(), - j->second.c_str()); - j++; - } - i++; - } + TemplateList templatelist(Conf::xml_basedir + "/templates"); ssize_t size; char buf[4096]; @@ -332,7 +325,8 @@ static void handleConnection(TCPSocket *socket) if(parser->parse(buf, size)) { PRACRO_DEBUG(server, "Got complete XML document %d bytes used, %d bytes in current buffer.\n", parser->usedBytes(), size); - socket->write(handleTransaction(transaction, pentominos_socket, db, journalwriter, macrolist)); + socket->write(handleTransaction(transaction, pentominos_socket, + db, journalwriter, macrolist, templatelist)); size = size - parser->usedBytes(); if(size) { strcpy(buf, buf + parser->usedBytes()); diff --git a/server/src/templateheaderparser.cc b/server/src/templateheaderparser.cc new file mode 100644 index 0000000..8b0f162 --- /dev/null +++ b/server/src/templateheaderparser.cc @@ -0,0 +1,142 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + * templateheaderparser.cc + * + * Thu Jul 30 08:53:26 CEST 2009 + * Copyright 2009 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Pracro. + * + * Pracro is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Pracro is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Pracro; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "templateheaderparser.h" + +#include + +// For assert +#include + +// For open and friends +#include +#include +#include +#include + +// For vprintf and friends +#include + +#include +#include + +#include "debug.h" +#include "configuration.h" +#include "exception.h" + +void TemplateHeaderParser::error(const char* fmt, ...) +{ + PRACRO_ERR_LOG(templateparser, "Error in TemplateHeaderParser: "); + + { + va_list argp; + va_start(argp, fmt); + PRACRO_ERR_LOG_VA(templateparser, fmt, argp); + va_end(argp); + + fprintf(stderr, "\n"); + } + + { + char *p; + va_list argp; + va_start(argp, fmt); + if(vasprintf(&p, fmt, argp) != -1) { + throw Exception("Error in TemplateHeaderParser: " + std::string(p)); + free(p); + } + va_end(argp); + } + +} + +TemplateHeaderParser::TemplateHeaderParser(std::string templatefile) +{ + t = NULL; + + file = templatefile; + + PRACRO_DEBUG(templateparser, "Using template file: %s\n", templatefile.c_str()); + + fd = open(templatefile.c_str(), O_RDONLY); + if(fd == -1) error("Could not open file %s", templatefile.c_str()); +} + +TemplateHeaderParser::~TemplateHeaderParser() +{ + if(fd != -1) close(fd); + if(t) delete t; +} + +void TemplateHeaderParser::startTag(std::string name, std::map< std::string, std::string> attributes) +{ + // Create template and enable parsing of queries, maps and window + if(name == "template") { + assert(!t); // A Template has already been allocated, cannot create template! + t = new Template(); + t->attributes = attributes; + } +} + +int TemplateHeaderParser::readData(char *data, size_t size) +{ + if(t) return 0; // If t is allocated, it means that we have parsed the template + // tag, and can dismiss the rest of the document. + + if(fd == -1) { + PRACRO_ERR_LOG(templateparser, "Invalid file descriptor.\n"); + return 0; + } + ssize_t r = read(fd, data, size); + if(r == -1) { + PRACRO_ERR_LOG(templateparser, "Could not read...%s\n", strerror(errno)); + return 0; + } + return r; +} + +void TemplateHeaderParser::parseError(char *buf, size_t len, std::string error, int lineno) +{ + if(t) return; // Ignore "unclosed token" errors when the template tag has been parsed. + + PRACRO_ERR_LOG(templateparser, "TemplateHeaderParser[%s] error at line %d: %s\n", file.c_str(), lineno, error.c_str()); + PRACRO_ERR_LOG(templateparser, "\tBuffer %u bytes: [", len); + if(fwrite(buf, len, 1, stderr) != len) {} + PRACRO_ERR_LOG(templateparser, "]\n"); + + char *slineno; + if(asprintf(&slineno, " at line %d\n", lineno) != -1) { + throw Exception(error + slineno); + free(slineno); + } + +} + +Template *TemplateHeaderParser::getTemplate() +{ + return t; +} diff --git a/server/src/templateheaderparser.h b/server/src/templateheaderparser.h new file mode 100644 index 0000000..522f56d --- /dev/null +++ b/server/src/templateheaderparser.h @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + * templateheaderparser.h + * + * Thu Jul 30 08:53:26 CEST 2009 + * Copyright 2009 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Pracro. + * + * Pracro is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Pracro is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Pracro; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __PRACRO_TEMPLATEHEADERPARSER_H__ +#define __PRACRO_TEMPLATEHEADERPARSER_H__ + +#include "saxparser.h" +#include "template.h" + +class TemplateHeaderParser : public SAXParser { +public: + TemplateHeaderParser(std::string templatefile); + ~TemplateHeaderParser(); + + void startTag(std::string name, std::map< std::string, std::string> attributes); + void parseError(char *buf, size_t len, std::string error, int lineno); + + /** + * Get a pointer to the parsed template. + * NOTE: The allocated memory for the template is owned by the parser, and will be + * freed upon parser deletion. + * @return A pointer to the template or NULL on error. + */ + Template *getTemplate(); + +protected: + int readData(char *data, size_t size); + +private: + int fd; + Template *t; + + std::string file; + // Error callback function. + void error(const char* fmt, ...); +}; + +#endif/*__PRACRO_TEMPLATEHEADERPARSER_H__*/ diff --git a/server/src/templatelist.cc b/server/src/templatelist.cc new file mode 100644 index 0000000..2e6f176 --- /dev/null +++ b/server/src/templatelist.cc @@ -0,0 +1,167 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + * templatelist.cc + * + * Thu Jul 30 08:52:30 CEST 2009 + * Copyright 2009 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Pracro. + * + * Pracro is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Pracro is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Pracro; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "templatelist.h" + +#include +#include + +#include "debug.h" +#include "templateheaderparser.h" + +static std::vector listdir(std::string path) +{ + std::vector files; + + DIR* dir = opendir(path.c_str()); + if(!dir) { + PRACRO_ERR(dump, "Could not open directory: %s\n", path.c_str()); + return files; + } + + struct dirent *d; + while((d = readdir(dir)) != 0) { + //if(d->d_type == DT_DIR) { + std::string name = d->d_name; + if(name.length() >= 4 && name.substr(name.length() - 4) == ".xml") + files.push_back(name); + //} + } + closedir(dir); + + return files; +} + +TemplateList::TemplateList(std::string templatepath) +{ + this->templatepath = templatepath; + std::vector templates = listdir(templatepath); + std::vector::iterator i = templates.begin(); + while(i != templates.end()) { + TemplateHeaderParser parser(templatepath + "/" + *i); + parser.parse(); + Template *templ = parser.getTemplate(); + (*this)[templ->attributes["name"]][VersionStr(templ->attributes["version"])] = *i; + i++; + } + + { + iterator i = begin(); + while(i != end()) { + TemplateListItem::iterator j = i->second.begin(); + while(j != i->second.end()) { + PRACRO_DEBUG(templatelist, "%s - v%s file: %s\n", + i->first.c_str(), + ((std::string)j->first).c_str(), + j->second.c_str()); + j++; + } + i++; + } + } + +} + +std::string TemplateList::getLatestVersion(std::string templ) throw(Exception) +{ + if(find(templ) == end()) throw Exception("Template ["+templ+"] does not exist"); + TemplateListItem mli = (*this)[templ]; + if(mli.size() == 0) return ""; + PRACRO_DEBUG(templatelist, "Search for %s - found %s v%s\n", + templ.c_str(), + (templatepath + "/" + mli.begin()->second).c_str(), + ((std::string)mli.begin()->first).c_str()); + return templatepath + "/" + mli.begin()->second; +} + +#ifdef TEST_TEMPLATELIST + +#define TEMPLATEDIR "/home" // We assume this directory exists and does not contain any xml files! + +int main() +{ + // Test sorting + TemplateList lst(TEMPLATEDIR); + + lst["template1"][VersionStr("1.0")] = "template1-1.0.xml"; + lst["template1"][VersionStr("1.1")] = "template1-1.1.xml"; + lst["template1"][VersionStr("1.1.1")] = "template1-1.1.1.xml"; + lst["template1"][VersionStr("1.2")] = "template1-1.2.xml"; + lst["template2"][VersionStr("1.0")] = "template2.xml"; + lst["template3"][VersionStr("1.0")] = "template3.xml"; + + std::vector refs; + refs.push_back("template1-1.2.xml"); + refs.push_back("template1-1.1.1.xml"); + refs.push_back("template1-1.1.xml"); + refs.push_back("template1-1.0.xml"); + refs.push_back("template2.xml"); + refs.push_back("template3.xml"); + + TemplateList::iterator i = lst.begin(); + std::vector::iterator k = refs.begin(); + while(i != lst.end()) { + TemplateListItem::iterator j = i->second.begin(); + while(j != i->second.end()) { + printf("%s - v%s file: %s - should be %s\n", + i->first.c_str(), + ((std::string)j->first).c_str(), + j->second.c_str(), + k->c_str()); + if(j->second != *k) return 1; + j++; k++; + } + i++; + } + + // Test lookup of latest versions. + std::string m1 = lst.getLatestVersion("template1"); + printf("Latest template1: %s\n", m1.c_str()); + if(m1 != TEMPLATEDIR"/template1-1.2.xml") return 1; + + std::string m2 = lst.getLatestVersion("template2"); + printf("Latest template2: %s\n", m2.c_str()); + if(m2 != TEMPLATEDIR"/template2.xml") return 1; + + std::string m3 = lst.getLatestVersion("template3"); + printf("Latest template3: %s\n", m3.c_str()); + if(m3 != TEMPLATEDIR"/template3.xml") return 1; + + // Look for non existing template (this should throw an exception) + try { + std::string m4 = lst.getLatestVersion("template4"); + } catch(Exception &e) { + printf("ERROR: %s\n", e.what()); + goto onandon; + } + return 1; + onandon: + + return 0; +} + +#endif/*TEST_TEMPLATELIST*/ diff --git a/server/src/templatelist.h b/server/src/templatelist.h new file mode 100644 index 0000000..bcf22f1 --- /dev/null +++ b/server/src/templatelist.h @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + * templatelist.h + * + * Thu Jul 30 08:52:30 CEST 2009 + * Copyright 2009 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Pracro. + * + * Pracro is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Pracro is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Pracro; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __PRACRO_TEMPLATELIST_H__ +#define __PRACRO_TEMPLATELIST_H__ + +#include +#include +#include "versionstr.h" + +#include "exception.h" + +/** + * The Items contained in the TemplateList. + */ +typedef std::map TemplateListItem; + +/** + * The TemplateList class is intended for template file caching, so that all templates + * do not need to be parsed on each template query. + * It builds a list of templates and versions based on the informations read from + * the TemplateHeaderParser. + * This means that just because a template gets into the list doesn't means that it + * will validate as a correct template (not even nessecarily correct XML). + */ +class TemplateList : public std::map { +public: + /** + * Constructor. + * @param templatepath A std::string containing the path in which we should look + * for xml files. + */ + TemplateList(std::string templatepath); + + /** + * Convenience method, to gain the filename of the latest version of a given template. + * This method throws an Exception if the template does not exist in the tree. + * @param template A std::string containing the name of the wanted template. + * @return A std::string containing the file containing the template with full path + * included. + */ + std::string getLatestVersion(std::string templ) throw(Exception); + +private: + std::string templatepath; +}; + +#endif/*__PRACRO_TEMPLATELIST_H__*/ diff --git a/server/src/templateparser.cc b/server/src/templateparser.cc index 49cc29d..8ddf6d2 100644 --- a/server/src/templateparser.cc +++ b/server/src/templateparser.cc @@ -57,13 +57,13 @@ void TemplateParser::error(const char* fmt, ...) free(p); } -TemplateParser::TemplateParser(std::string course) +TemplateParser::TemplateParser(std::string templatefile) { state = UNDEFINED; t = new Template(); current_macro = NULL; - file = Conf::xml_basedir + "/templates/" + course + ".xml"; + file = templatefile;//Conf::xml_basedir + "/templates/" + course + ".xml"; PRACRO_DEBUG(macro, "Using template file: %s\n", file.c_str()); @@ -168,7 +168,7 @@ int main() Conf::xml_basedir = "../xml/"; try { - TemplateParser parser("example"); + TemplateParser parser("../xml/templates/example.xml"); parser.parse(); Template *t = parser.getTemplate(); diff --git a/server/src/transactionparser.cc b/server/src/transactionparser.cc index 08c0a42..3135929 100644 --- a/server/src/transactionparser.cc +++ b/server/src/transactionparser.cc @@ -68,10 +68,6 @@ TransactionParser::TransactionParser(Transaction *transaction) totalbytes = 0; } -TransactionParser::~TransactionParser() -{ -} - void TransactionParser::startTag(std::string name, std::map< std::string, std::string> attributes) { if(name == "pracro") { diff --git a/server/xml/templates/example.xml b/server/xml/templates/example.xml index 2fdbb9c..b6a3f6d 100644 --- a/server/xml/templates/example.xml +++ b/server/xml/templates/example.xml @@ -1,14 +1,6 @@ - - - - - - + +
- + -- cgit v1.2.3