/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set et sw=2 ts=2: */ /*************************************************************************** * transactionhandler.cc * * Fri Dec 18 10:00:50 CET 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 "transactionhandler.h" #include "macroparser.h" #include "resumeparser.h" #include "templateparser.h" #include "configuration.h" #include "luaquerymapper.h" #include "queryhandlerpentominos.h" #include "queryhandlerpracro.h" #include "xml_encode_decode.h" #include "widgetgenerator.h" #include "journal.h" static std::string error_box(std::string message) { std::string errorbox = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<pracro version=\"1.0\">\n" " <error>" + message + "</error>\n" "</pracro>\n"; return errorbox; } static std::string handleCommits(Transaction &transaction, Environment &env, Session &session) { std::string answer; if(transaction.commits.size() > 0) { // AutoBorrower<Database*> borrower(env.dbpool); // Database *db = borrower.get(); Database *db = session.database(); Commits::iterator i = transaction.commits.begin(); while(i != transaction.commits.end()) { Commit &commit = *i; MacroParser mp(env.macrolist.getLatestVersion(commit.macro)); mp.parse(); Macro *macro = mp.getMacro(); std::string resume = resume_parser(*macro, commit); commit.fields["journal.resume"] = resume; db->commitTransaction(transaction, commit, *macro); if(resume != "") { TemplateParser tp(env.templatelist.getLatestVersion(commit.templ)); tp.parse(); Template *templ = tp.getTemplate(); session.journal()->addEntry(transaction, commit, resume, templ); } i++; } } return answer; } static std::string handleRequest(Transaction &transaction, Environment &env, Session &session) { std::string answer; if(transaction.requests.size() > 0) { // AutoBorrower<Database*> borrower(env.dbpool); // Database *db = borrower.get(); Database *db = session.database(); Requests::iterator i = transaction.requests.begin(); while(i != transaction.requests.end()) { Request &request = *i; DEBUG(server, "Handling request - macro: %s, template: %s\n", request.macro.c_str(), request.templ.c_str()); // Read and parse the template file. TemplateParser tp(env.templatelist.getLatestVersion(request.templ)); tp.parse(); Template *templ = tp.getTemplate(); answer += " <template name=\""; answer += templ->attributes["name"]; answer += "\" title=\""; answer += templ->attributes["title"]; answer += "\">\n"; bool foundmacro = false; // Generate the macro and return it to the client std::vector< Macro >::iterator mi2 = templ->macros.begin(); while(mi2 != templ->macros.end()) { Macro ¯o = (*mi2); if(macro.isHeader) { answer += " <header caption=\"" + macro.attributes["caption"] + "\"/>\n"; mi2++; continue; } bool completed = db->checkMacro(transaction.cpr, macro.attributes["name"], time(NULL)-Conf::db_max_ttl); answer += " <macro uid=\"42\" completed="; if(completed) answer += "\"true\""; else answer += "\"false\""; std::map< std::string, std::string >::iterator ai = macro.attributes.begin(); while(ai != macro.attributes.end()) { std::string name = ai->first; std::string value = ai->second; answer += " "+name+"=\"" + value + "\""; ai++; } if(macro.attributes["name"] == request.macro || (macro.attributes.find("static") != macro.attributes.end() && macro.attributes["static"] == "true") ) { foundmacro = true; MacroParser mp(env.macrolist.getLatestVersion(macro.attributes["name"])); mp.parse(); Macro *m = mp.getMacro(); answer += " caption=\"" + m->widgets.attributes["caption"] + "\""; answer += ">\n"; AutoBorrower<Artefact*> borrower(env.atfpool); Artefact *atf = borrower.get(); LUAQueryMapper lqm; //////////////////////// std::vector< Query >::iterator qi = m->queries.begin(); while(qi != m->queries.end()) { Query &query = *qi; std::string service = query.attributes["service"]; if(service == "pentominos") { // Send the queries to Pentominos (if any) QueryHandlerPentominos qh(*atf, transaction.cpr, "pracrod"/*user*/); QueryResult queryresult = qh.exec(*qi); lqm.addQueryResult(queryresult); } if(service == "pracro") { // Send the queries to Pentominos (if any) QueryHandlerPracro qh(*db, transaction.cpr); QueryResult queryresult = qh.exec(*qi); lqm.addQueryResult(queryresult); } qi++; } // Handle scripts if(m->scripts.size()) { answer += " <scripts>\n"; std::vector< Script >::iterator spi = m->scripts.begin(); while(spi != m->scripts.end()) { // answer += " <script language=\"" + // spi->attributes["language"] + "\">"; answer += " <script>"; if(spi->attributes.find("src") != spi->attributes.end()) { std::string file = Conf::xml_basedir + "/include/" + spi->attributes["src"]; FILE *fp = fopen(file.c_str(), "r"); if(fp) { char buf[64]; size_t sz; std::string inc; while((sz = fread(buf, 1, sizeof(buf), fp)) != 0) { inc.append(buf, sz); } fclose(fp); answer += "\n-- BEGIN INCLUDE: '" + spi->attributes["src"] + "'\n"; answer += xml_encode(inc); answer += "\n-- END INCLUDE: '" + spi->attributes["src"] + "'\n"; } } else { answer += xml_encode(spi->attributes["code"]); } answer += "</script>\n"; spi++; } answer += " </scripts>\n"; } answer += widgetgenerator(transaction.cpr, *m, lqm, *db); } else { // only find macro title MacroParser mp(env.macrolist.getLatestVersion(macro.attributes["name"])); mp.parse(); Macro *m = mp.getMacro(); answer += " caption=\"" + m->widgets.attributes["caption"] + "\""; answer += ">\n"; } if(completed) { std::string jresume = session.journal()->getEntry(macro.attributes["name"]); std::string state = "old"; std::string resume = db->getResume(transaction.cpr, macro, time(NULL) - Conf::db_max_ttl); if(session.journal()->dirty(macro.attributes["name"])) { state = "dirty"; } else { if(resume == jresume) { state = "new"; } else { if(jresume != "") { state = "dirty"; session.journal()->setDirty(macro.attributes["name"]); } else { state = "old"; } } } answer += " <resume state=\""+state+"\">"; answer += xml_encode(resume); answer += "</resume>\n"; } answer += " </macro>\n"; mi2++; } if(foundmacro == false && request.macro != "") throw NotFoundException(request); answer += " </template>\n"; i++; } } return answer; } std::string handleTransaction(Transaction &transaction, Environment &env, Session &session) { std::string answer; answer += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; answer += "<pracro version=\"1.0\">\n"; try { answer += handleCommits(transaction, env, session); } catch( std::exception &e ) { ERR(server, "Commit error: %s\n", e.what()); return error_box(xml_encode(e.what())); } try { answer += handleRequest(transaction, env, session); } catch( std::exception &e ) { ERR(server, "Request error: %s\n", e.what()); return error_box(xml_encode(e.what())); } answer += "</pracro>\n"; DEBUG(server, "Done handling transaction\n"); DEBUG(serverxml, "%s\n", answer.c_str()); return answer; } #ifdef TEST_TRANSACTIONHANDLER //deps: //cflags: -I.. //libs: #include "test.h" TEST_BEGIN; #error TODO: Put some testcode here (see test.h for usable macros). TEST_END; #endif/*TEST_TRANSACTIONHANDLER*/