diff options
Diffstat (limited to 'server/src')
| -rw-r--r-- | server/src/Makefile.am | 14 | ||||
| -rw-r--r-- | server/src/macrolist.cc | 15 | ||||
| -rw-r--r-- | server/src/server.cc | 28 | ||||
| -rw-r--r-- | server/src/templateheaderparser.cc | 142 | ||||
| -rw-r--r-- | server/src/templateheaderparser.h | 62 | ||||
| -rw-r--r-- | server/src/templatelist.cc | 167 | ||||
| -rw-r--r-- | server/src/templatelist.h | 72 | ||||
| -rw-r--r-- | server/src/templateparser.cc | 6 | ||||
| -rw-r--r-- | server/src/transactionparser.cc | 4 | 
9 files changed, 486 insertions, 24 deletions
| 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 += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\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 <stdio.h> + +// For assert +#include <assert.h> + +// For open and friends +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +// For vprintf and friends +#include <stdarg.h> + +#include <errno.h> +#include <string.h> + +#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 <sys/types.h> +#include <dirent.h> + +#include "debug.h" +#include "templateheaderparser.h" + +static std::vector<std::string> listdir(std::string path) +{ +  std::vector<std::string> 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<std::string> templates = listdir(templatepath); +  std::vector<std::string>::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<std::string> 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<std::string>::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 <map> +#include <string> +#include "versionstr.h" + +#include "exception.h" + +/** + * The Items contained in the TemplateList. + */ +typedef std::map<VersionStr, std::string> 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<std::string, TemplateListItem > { +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") { | 
