platform/services/ConfigService.cpp

00001 // ------------------------------------------------------------------------
00002 // Pion is a development platform for building Reactors that process Events
00003 // ------------------------------------------------------------------------
00004 // Copyright (C) 2007-2008 Atomic Labs, Inc.  (http://www.atomiclabs.com)
00005 //
00006 // Pion is free software: you can redistribute it and/or modify it under the
00007 // terms of the GNU Affero General Public License as published by the Free
00008 // Software Foundation, either version 3 of the License, or (at your option)
00009 // any later version.
00010 //
00011 // Pion is distributed in the hope that it will be useful, but WITHOUT ANY
00012 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00013 // FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for
00014 // more details.
00015 //
00016 // You should have received a copy of the GNU Affero General Public License
00017 // along with Pion.  If not, see <http://www.gnu.org/licenses/>.
00018 //
00019 
00020 #include <sstream>
00021 #include <boost/filesystem.hpp>
00022 #include <boost/filesystem/operations.hpp>
00023 #include <pion/net/HTTPResponseWriter.hpp>
00024 #include <pion/platform/Comparison.hpp>
00025 #include "PlatformConfig.hpp"
00026 #include "ConfigService.hpp"
00027 
00028 using namespace pion::net;
00029 using namespace pion::server;
00030 using namespace pion::platform;
00031 
00032 
00033 namespace pion {        // begin namespace pion
00034 namespace plugins {     // begin namespace plugins
00035 
00036 
00037 // static members of ConfigService
00038 const std::string       ConfigService::UI_DIRECTORY_ELEMENT_NAME = "UIDirectory";
00039 
00040 
00041 // ConfigService member functions
00042 
00043 void ConfigService::setConfig(const pion::platform::Vocabulary& v,
00044                               const xmlNodePtr config_ptr)
00045 {
00046     pion::server::PlatformService::setConfig(v, config_ptr);
00047 
00048     // get the UI directory
00049     if (! ConfigManager::getConfigOption(UI_DIRECTORY_ELEMENT_NAME, m_ui_directory, config_ptr))
00050         throw MissingUIDirectoryException();
00051 }
00052 
00053 void ConfigService::operator()(HTTPRequestPtr& request, TCPConnectionPtr& tcp_conn)
00054 {
00055     // split out the path branches from the HTTP request
00056     PathBranches branches;
00057     splitPathBranches(branches, request->getResource());
00058 
00059     // use a response in case we want to change any of the headers/etc.
00060     // while processing the request
00061     HTTPResponsePtr response_ptr(new HTTPResponse(*request));
00062 
00063     // use a stringstream for the response content
00064     // since HTTPResponseWriter does not yet have a stream wrapper available
00065     std::stringstream ss;
00066 
00067     PlatformConfig& cfg = getConfig();
00068 
00069     try {
00070 
00071         if (branches.empty()) {
00072 
00073             // send platform configuration info
00074             cfg.writeConfigXML(ss);
00075 
00076         } else if (branches.front() == "vocabularies") {
00077             //
00078             // BEGIN VOCABULARIES CONFIG
00079             //
00080             if (branches.size() == 1) {
00081 
00082                 // returns a list of all Vocabularies
00083                 cfg.getVocabularyManager().writeConfigXML(ss);
00084 
00085             } else if (branches.size() == 2) {
00086                 // branches[1] == vocabulary_id
00087                 const std::string vocab_id(branches[1]);
00088 
00089                 if (request->getMethod() == HTTPTypes::REQUEST_METHOD_GET) {
00090                     // retrieve an existing Vocabulary's configuration
00091 
00092                     if (! cfg.getVocabularyManager().writeConfigXML(ss, vocab_id))
00093                         throw VocabularyManager::VocabularyNotFoundException(vocab_id);
00094 
00095                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_POST) {
00096 
00097                     // add (create) a new Vocabulary
00098 
00099                     // Check whether the User has permission to create the specified Vocabulary.
00100                     if (cfg.getUserManagerPtr()->creationAllowed(request->getUser(), cfg.getVocabularyManager(), NULL)) {
00101                         cfg.getVocabularyManager().addVocabulary(vocab_id,
00102                                                                  request->getContent(),
00103                                                                  request->getContentLength());
00104                         // send a 201 (Created) response
00105                         response_ptr->setStatusCode(HTTPTypes::RESPONSE_CODE_CREATED);
00106                         response_ptr->setStatusMessage(HTTPTypes::RESPONSE_MESSAGE_CREATED);
00107 
00108                         // respond with the new Vocabulary's configuration
00109                         if (! cfg.getVocabularyManager().writeConfigXML(ss, vocab_id))
00110                             throw VocabularyManager::VocabularyNotFoundException(vocab_id);
00111                     } else {
00112                         // Log an error and send a 403 (Forbidden) response.
00113                         std::string error_msg = "User doesn't have permission to create a Vocabulary.";
00114                         handleForbiddenRequest(request, tcp_conn, error_msg);
00115                         return;
00116                     }
00117 
00118                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_PUT) {
00119                     // update existing Vocabulary's configuration
00120 
00121                     // convert request content into XML configuration info
00122                     xmlNodePtr vocab_config_ptr =
00123                         VocabularyConfig::createVocabularyConfig(request->getContent(),
00124                                                                  request->getContentLength());
00125 
00126                     // Check whether the User has permission to make the specified modification to the specified Vocabulary.
00127                     if (cfg.getUserManagerPtr()->updateAllowed(request->getUser(), cfg.getVocabularyManager(), vocab_id, vocab_config_ptr)) {
00128                         try {
00129                             // push the new config into the VocabularyManager
00130                             cfg.getVocabularyManager().setVocabularyConfig(vocab_id, vocab_config_ptr);
00131                         } catch (std::exception&) {
00132                             xmlFreeNodeList(vocab_config_ptr);
00133                             throw;
00134                         }
00135                         xmlFreeNodeList(vocab_config_ptr);
00136 
00137                         // respond with the Vocabulary's updated configuration
00138                         if (! cfg.getVocabularyManager().writeConfigXML(ss, vocab_id))
00139                             throw VocabularyManager::VocabularyNotFoundException(vocab_id);
00140                     } else {
00141                         xmlFreeNodeList(vocab_config_ptr);
00142 
00143                         // Log an error and send a 403 (Forbidden) response.
00144                         std::string error_msg = "User doesn't have permission to modify Vocabulary " + vocab_id + ".";
00145                         handleForbiddenRequest(request, tcp_conn, error_msg);
00146                         return;
00147                     }
00148 
00149                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_DELETE) {
00150                     // delete an existing Vocabulary
00151 
00152                     // Check whether the User has permission to remove the specified Vocabulary.
00153                     if (cfg.getUserManagerPtr()->removalAllowed(request->getUser(), cfg.getVocabularyManager(), vocab_id)) {
00154                         cfg.getVocabularyManager().removeVocabulary(vocab_id);
00155 
00156                         // send a 204 (No Content) response
00157                         response_ptr->setStatusCode(HTTPTypes::RESPONSE_CODE_NO_CONTENT);
00158                         response_ptr->setStatusMessage(HTTPTypes::RESPONSE_MESSAGE_NO_CONTENT);
00159                     } else {
00160                         // Log an error and send a 403 (Forbidden) response.
00161                         std::string error_msg = "User doesn't have permission to delete Vocabulary " + vocab_id + ".";
00162                         handleForbiddenRequest(request, tcp_conn, error_msg);
00163                         return;
00164                     }
00165 
00166                 } else {
00167                     // Log an error and send a 405 (Method Not Allowed) response.
00168                     handleMethodNotAllowed(request, tcp_conn, "GET, POST, PUT, DELETE");
00169                     return;
00170                 }
00171 
00172             } else {
00173                 // Log an error and send a 404 (Not Found) response.
00174                 handleNotFoundRequest(request, tcp_conn);
00175                 return;
00176             }
00177             //
00178             // END VOCABULARIES CONFIG
00179             //
00180         } else if (branches.front() == "terms") {
00181             //
00182             // BEGIN TERMS CONFIG
00183             //
00184             if (branches.size() == 1) {
00185 
00186                 // return a list of all Terms
00187                 cfg.getVocabularyManager().writeTermConfigXML(ss);
00188 
00189             } else if (branches.size() == 2) {
00190                 // branches[1] == term_id
00191                 const std::string term_id(branches[1]);
00192                 const std::string vocab_id(term_id.substr(0, term_id.find_last_of('#')));
00193 
00194                 if (request->getMethod() == HTTPTypes::REQUEST_METHOD_GET) {
00195                     // retrieve an existing Vocabulary Term's configuration
00196 
00197                     if (! cfg.getVocabularyManager().writeTermConfigXML(ss, term_id))
00198                         throw Vocabulary::TermNotFoundException(term_id);
00199 
00200                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_POST) {
00201 
00202                     // add (create) a new Vocabulary Term
00203 
00204                     // convert request content into XML configuration info
00205                     xmlNodePtr term_config_ptr =
00206                         VocabularyConfig::createTermConfig(request->getContent(),
00207                                                            request->getContentLength());
00208 
00209                     // Check whether the User has permission to create the specified Vocabulary Term.
00210                     if (cfg.getUserManagerPtr()->creationAllowed(request->getUser(), cfg.getVocabularyManager(), term_config_ptr)) {
00211 
00212                         // add the new Vocabulary Term to the VocabularyManager
00213                         try {
00214                             cfg.getVocabularyManager().addTerm(vocab_id, term_id, term_config_ptr);
00215                         } catch (std::exception&) {
00216                             xmlFreeNodeList(term_config_ptr);
00217                             throw;
00218                         }
00219                         xmlFreeNodeList(term_config_ptr);
00220 
00221                         // send a 201 (created) response
00222                         response_ptr->setStatusCode(HTTPTypes::RESPONSE_CODE_CREATED);
00223                         response_ptr->setStatusMessage(HTTPTypes::RESPONSE_MESSAGE_CREATED);
00224 
00225                         // respond with the new Vocabulary Term's configuration
00226                         if (! cfg.getVocabularyManager().writeTermConfigXML(ss, term_id))
00227                             throw Vocabulary::TermNotFoundException(term_id);
00228 
00229                     } else {
00230                         // Log an error and send a 403 (Forbidden) response.
00231                         std::string error_msg = "User doesn't have permission to create a Vocabulary Term.";
00232                         handleForbiddenRequest(request, tcp_conn, error_msg);
00233                         return;
00234                     }
00235 
00236                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_PUT) {
00237                     // update existing Vocabulary Term's configuration
00238 
00239                     // convert request content into XML configuration info
00240                     xmlNodePtr term_config_ptr =
00241                         VocabularyConfig::createTermConfig(request->getContent(),
00242                                                            request->getContentLength());
00243 
00244                     // Check whether the User has permission to make the specified modification to the specified Vocabulary Term.
00245                     if (cfg.getUserManagerPtr()->updateAllowed(request->getUser(), cfg.getVocabularyManager(), term_id, term_config_ptr)) {
00246                         try {
00247                             // push the new config into the VocabularyManager
00248                             cfg.getVocabularyManager().updateTerm(vocab_id, term_id, term_config_ptr);
00249                         } catch (std::exception&) {
00250                             xmlFreeNodeList(term_config_ptr);
00251                             throw;
00252                         }
00253                         xmlFreeNodeList(term_config_ptr);
00254 
00255                         // respond with the Vocabulary Term's updated configuration
00256                         if (! cfg.getVocabularyManager().writeTermConfigXML(ss, term_id))
00257                             throw Vocabulary::TermNotFoundException(term_id);
00258 
00259                     } else {
00260                         xmlFreeNodeList(term_config_ptr);
00261 
00262                         // Log an error and send a 403 (Forbidden) response.
00263                         std::string error_msg = "User doesn't have permission to modify Vocabulary Term " + term_id + ".";
00264                         handleForbiddenRequest(request, tcp_conn, error_msg);
00265                         return;
00266                     }
00267 
00268                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_DELETE) {
00269                     // delete an existing Vocabulary Term
00270 
00271                     // Check whether the User has permission to remove the specified Vocabulary Term.
00272                     if (cfg.getUserManagerPtr()->removalAllowed(request->getUser(), cfg.getVocabularyManager(), term_id)) {
00273                         cfg.getVocabularyManager().removeTerm(vocab_id, term_id);
00274 
00275                         // send a 204 (No Content) response
00276                         response_ptr->setStatusCode(HTTPTypes::RESPONSE_CODE_NO_CONTENT);
00277                         response_ptr->setStatusMessage(HTTPTypes::RESPONSE_MESSAGE_NO_CONTENT);
00278                     } else {
00279                         // Log an error and send a 403 (Forbidden) response.
00280                         std::string error_msg = "User doesn't have permission to delete Vocabulary Term " + term_id + ".";
00281                         handleForbiddenRequest(request, tcp_conn, error_msg);
00282                         return;
00283                     }
00284 
00285                 } else {
00286                     // Log an error and send a 405 (Method Not Allowed) response.
00287                     handleMethodNotAllowed(request, tcp_conn, "GET, POST, PUT, DELETE");
00288                     return;
00289                 }
00290 
00291             } else {
00292                 // Log an error and send a 404 (Not Found) response.
00293                 handleNotFoundRequest(request, tcp_conn);
00294                 return;
00295             }
00296             //
00297             // END TERMS CONFIG
00298             //
00299         } else if (branches.front() == "comparisons") {
00300             //
00301             // BEGIN COMPARISONS CONFIG
00302             //
00303             if (branches.size() == 1) {
00304 
00305                 // returns a list of all Comparisons
00306                 ConfigManager::writeBeginPionConfigXML(ss);
00307                 Comparison::writeComparisonsXML(ss);
00308                 ConfigManager::writeEndPionConfigXML(ss);
00309 
00310             } else {
00311                 // Log an error and send a 404 (Not Found) response.
00312                 handleNotFoundRequest(request, tcp_conn);
00313                 return;
00314             }
00315             //
00316             // END COMPARISONS CONFIG
00317             //
00318         } else if (branches.front() == "codecs") {
00319             //
00320             // BEGIN CODECS CONFIG
00321             //
00322             if (branches.size() == 1) {
00323                 if (request->getMethod() == HTTPTypes::REQUEST_METHOD_GET) {
00324 
00325                     // retrieve configuration for all Codecs
00326                     cfg.getCodecFactory().writeConfigXML(ss);
00327 
00328                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_POST) {
00329 
00330                     // add (create) a new Codec
00331 
00332                     // convert request content into XML configuration info
00333                     xmlNodePtr codec_config_ptr =
00334                         CodecFactory::createCodecConfig(request->getContent(),
00335                                                         request->getContentLength());
00336 
00337                     // Check whether the User has permission to create the specified Codec.
00338                     if (cfg.getUserManagerPtr()->creationAllowed(request->getUser(), cfg.getCodecFactory(), codec_config_ptr)) {
00339                         // add the new Codec to the CodecFactory
00340                         std::string codec_id;
00341                         try {
00342                             codec_id = cfg.getCodecFactory().addCodec(codec_config_ptr);
00343                         } catch (std::exception&) {
00344                             xmlFreeNodeList(codec_config_ptr);
00345                             throw;
00346                         }
00347 
00348                         xmlFreeNodeList(codec_config_ptr);
00349 
00350                         // send a 201 (Created) response
00351                         response_ptr->setStatusCode(HTTPTypes::RESPONSE_CODE_CREATED);
00352                         response_ptr->setStatusMessage(HTTPTypes::RESPONSE_MESSAGE_CREATED);
00353 
00354                         // respond with the new Codec's configuration
00355                         if (! cfg.getCodecFactory().writeConfigXML(ss, codec_id))
00356                             throw CodecFactory::CodecNotFoundException(codec_id);
00357                     } else {
00358                         xmlFreeNodeList(codec_config_ptr);
00359 
00360                         // Log an error and send a 403 (Forbidden) response.
00361                         std::string error_msg = "User doesn't have permission to create a Codec.";
00362                         handleForbiddenRequest(request, tcp_conn, error_msg);
00363                         return;
00364                     }
00365 
00366                 } else {
00367                     // Log an error and send a 405 (Method Not Allowed) response.
00368                     handleMethodNotAllowed(request, tcp_conn, "GET, POST");
00369                     return;
00370                 }
00371 
00372             } else if (branches.size() == 2) {
00373                 // branches[1] == codec_id
00374 
00375                 if (request->getMethod() == HTTPTypes::REQUEST_METHOD_GET) {
00376                     // retrieve an existing Codec's configuration
00377 
00378                     if (! cfg.getCodecFactory().writeConfigXML(ss, branches[1]))
00379                         throw CodecFactory::CodecNotFoundException(branches[1]);
00380 
00381                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_PUT) {
00382                     // update existing Codec's configuration
00383 
00384                     // convert request content into XML configuration info
00385                     xmlNodePtr codec_config_ptr =
00386                         CodecFactory::createCodecConfig(request->getContent(),
00387                                                         request->getContentLength());
00388 
00389                     // Check whether the User has permission to make the specified modification to the specified Codec.
00390                     if (cfg.getUserManagerPtr()->updateAllowed(request->getUser(), cfg.getCodecFactory(), branches[1], codec_config_ptr)) {
00391                         try {
00392                             // push the new config into the CodecFactory
00393                             cfg.getCodecFactory().setCodecConfig(branches[1], codec_config_ptr);
00394                         } catch (std::exception&) {
00395                             xmlFreeNodeList(codec_config_ptr);
00396                             throw;
00397                         }
00398                         xmlFreeNodeList(codec_config_ptr);
00399 
00400                         // respond with the Codec's updated configuration
00401                         if (! cfg.getCodecFactory().writeConfigXML(ss, branches[1]))
00402                             throw CodecFactory::CodecNotFoundException(branches[1]);
00403                     } else {
00404                         xmlFreeNodeList(codec_config_ptr);
00405 
00406                         // Log an error and send a 403 (Forbidden) response.
00407                         std::string error_msg = "User doesn't have permission to modify Codec " + branches[1] + ".";
00408                         handleForbiddenRequest(request, tcp_conn, error_msg);
00409                         return;
00410                     }
00411 
00412                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_DELETE) {
00413                     // delete an existing Codec
00414 
00415                     // Check whether the User has permission to remove the specified Codec.
00416                     if (cfg.getUserManagerPtr()->removalAllowed(request->getUser(), cfg.getCodecFactory(), branches[1])) {
00417                         cfg.getCodecFactory().removeCodec(branches[1]);
00418 
00419                         // send a 204 (No Content) response
00420                         response_ptr->setStatusCode(HTTPTypes::RESPONSE_CODE_NO_CONTENT);
00421                         response_ptr->setStatusMessage(HTTPTypes::RESPONSE_MESSAGE_NO_CONTENT);
00422                     } else {
00423                         // Log an error and send a 403 (Forbidden) response.
00424                         std::string error_msg = "User doesn't have permission to delete Codec " + branches[1] + ".";
00425                         handleForbiddenRequest(request, tcp_conn, error_msg);
00426                         return;
00427                     }
00428 
00429                 } else {
00430                     // Log an error and send a 405 (Method Not Allowed) response.
00431                     handleMethodNotAllowed(request, tcp_conn, "GET, PUT, DELETE");
00432                     return;
00433                 }
00434 
00435             } else {
00436                 // Log an error and send a 404 (Not Found) response.
00437                 handleNotFoundRequest(request, tcp_conn);
00438                 return;
00439             }
00440             //
00441             // END CODECS CONFIG
00442             //
00443         } else if (branches.front() == "databases") {
00444             //
00445             // BEGIN DATABASES CONFIG
00446             //
00447             if (branches.size() == 1) {
00448                 if (request->getMethod() == HTTPTypes::REQUEST_METHOD_GET) {
00449 
00450                     // retrieve configuration for all Databases
00451                     cfg.getDatabaseManager().writeConfigXML(ss);
00452 
00453                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_POST) {
00454 
00455                     // add (create) a new Database
00456 
00457                     // convert request content into XML configuration info
00458                     xmlNodePtr database_config_ptr =
00459                         DatabaseManager::createDatabaseConfig(request->getContent(),
00460                                                               request->getContentLength());
00461 
00462                     // Check whether the User has permission to create the specified Database.
00463                     if (cfg.getUserManagerPtr()->creationAllowed(request->getUser(), cfg.getDatabaseManager(), database_config_ptr)) {
00464                         // add the new Database to the DatabaseManager
00465                         std::string database_id;
00466                         try {
00467                             database_id = cfg.getDatabaseManager().addDatabase(database_config_ptr);
00468                         } catch (std::exception&) {
00469                             xmlFreeNodeList(database_config_ptr);
00470                             throw;
00471                         }
00472                         xmlFreeNodeList(database_config_ptr);
00473 
00474                         // send a 201 (Created) response
00475                         response_ptr->setStatusCode(HTTPTypes::RESPONSE_CODE_CREATED);
00476                         response_ptr->setStatusMessage(HTTPTypes::RESPONSE_MESSAGE_CREATED);
00477 
00478                         // respond with the new Database's configuration
00479                         if (! cfg.getDatabaseManager().writeConfigXML(ss, database_id))
00480                             throw DatabaseManager::DatabaseNotFoundException(database_id);
00481                     } else {
00482                         xmlFreeNodeList(database_config_ptr);
00483 
00484                         // Log an error and send a 403 (Forbidden) response.
00485                         std::string error_msg = "User doesn't have permission to create a Database.";
00486                         handleForbiddenRequest(request, tcp_conn, error_msg);
00487                         return;
00488                     }
00489 
00490                 } else {
00491                     // Log an error and send a 405 (Method Not Allowed) response.
00492                     handleMethodNotAllowed(request, tcp_conn, "GET, POST");
00493                     return;
00494                 }
00495 
00496             } else if (branches[1] == "plugins") {
00497 
00498                 // Send a list of all Databases found in the UI directory
00499 
00500                 ConfigManager::writeBeginPionConfigXML(ss);
00501 
00502                 // Iterate through all the subdirectories of the Database directory (e.g. SQLiteDatabase).
00503                 std::string database_directory = m_ui_directory + "/plugins/databases";
00504                 boost::filesystem::directory_iterator end;
00505                 for (boost::filesystem::directory_iterator it(database_directory); it != end; ++it) {
00506                     if (boost::filesystem::is_directory(*it)) {
00507                         // Skip directories starting with a '.'.
00508                         if (it->path().leaf().substr(0, 1) == ".") continue;
00509 
00510                         ss << "<Database>"
00511                            << "<Plugin>" << it->path().leaf() << "</Plugin>"
00512                            << "</Database>";
00513                     }
00514                 }
00515 
00516                 ConfigManager::writeEndPionConfigXML(ss);
00517 
00518             } else if (branches.size() == 2) {
00519                 // branches[1] == database_id
00520 
00521                 if (request->getMethod() == HTTPTypes::REQUEST_METHOD_GET) {
00522                     // retrieve an existing Database's configuration
00523 
00524                     if (! cfg.getDatabaseManager().writeConfigXML(ss, branches[1]))
00525                         throw DatabaseManager::DatabaseNotFoundException(branches[1]);
00526 
00527                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_PUT) {
00528                     // update existing Database's configuration
00529 
00530                     // convert request content into XML configuration info
00531                     xmlNodePtr database_config_ptr =
00532                         DatabaseManager::createDatabaseConfig(request->getContent(),
00533                                                               request->getContentLength());
00534 
00535                     // Check whether the User has permission to make the specified modification to the specified Database.
00536                     if (cfg.getUserManagerPtr()->updateAllowed(request->getUser(), cfg.getDatabaseManager(), branches[1], database_config_ptr)) {
00537                         try {
00538                             // push the new config into the DatabaseManager
00539                             cfg.getDatabaseManager().setDatabaseConfig(branches[1], database_config_ptr);
00540                         } catch (std::exception&) {
00541                             xmlFreeNodeList(database_config_ptr);
00542                             throw;
00543                         }
00544                         xmlFreeNodeList(database_config_ptr);
00545 
00546                         // respond with the Database's updated configuration
00547                         if (! cfg.getDatabaseManager().writeConfigXML(ss, branches[1]))
00548                             throw DatabaseManager::DatabaseNotFoundException(branches[1]);
00549 
00550                     } else {
00551                         xmlFreeNodeList(database_config_ptr);
00552 
00553                         // Log an error and send a 403 (Forbidden) response.
00554                         std::string error_msg = "User doesn't have permission to modify Database " + branches[1] + ".";
00555                         handleForbiddenRequest(request, tcp_conn, error_msg);
00556                         return;
00557                     }
00558                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_DELETE) {
00559                     // delete an existing Database
00560 
00561                     // Check whether the User has permission to remove the specified Database.
00562                     if (cfg.getUserManagerPtr()->removalAllowed(request->getUser(), cfg.getDatabaseManager(), branches[1])) {
00563                         cfg.getDatabaseManager().removeDatabase(branches[1]);
00564 
00565                         // send a 204 (No Content) response
00566                         response_ptr->setStatusCode(HTTPTypes::RESPONSE_CODE_NO_CONTENT);
00567                         response_ptr->setStatusMessage(HTTPTypes::RESPONSE_MESSAGE_NO_CONTENT);
00568                     } else {
00569                         // Log an error and send a 403 (Forbidden) response.
00570                         std::string error_msg = "User doesn't have permission to delete Database " + branches[1] + ".";
00571                         handleForbiddenRequest(request, tcp_conn, error_msg);
00572                         return;
00573                     }
00574 
00575                 } else {
00576                     // Log an error and send a 405 (Method Not Allowed) response.
00577                     handleMethodNotAllowed(request, tcp_conn, "GET, PUT, DELETE");
00578                     return;
00579                 }
00580 
00581             } else {
00582                 // Log an error and send a 404 (Not Found) response.
00583                 handleNotFoundRequest(request, tcp_conn);
00584                 return;
00585             }
00586             //
00587             // END DATABASES CONFIG
00588             //
00589         } else if (branches.front() == "protocols") {
00590             //
00591             // BEGIN PROTOCOLS CONFIG
00592             //
00593             if (branches.size() == 1) {
00594                 if (request->getMethod() == HTTPTypes::REQUEST_METHOD_GET) {
00595 
00596                     // retrieve configuration for all Protocols
00597                     cfg.getProtocolFactory().writeConfigXML(ss);
00598 
00599                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_POST) {
00600 
00601                     // add (create) a new Protocol
00602 
00603                     // convert request content into XML configuration info
00604                     xmlNodePtr protocol_config_ptr =
00605                         ProtocolFactory::createProtocolConfig(request->getContent(),
00606                                                               request->getContentLength());
00607 
00608                     // Check whether the User has permission to create the specified Protocol.
00609                     if (cfg.getUserManagerPtr()->creationAllowed(request->getUser(), cfg.getProtocolFactory(), protocol_config_ptr)) {
00610                         // add the new Protocol to the ProtocolFactory
00611                         std::string protocol_id;
00612                         try {
00613                             protocol_id = cfg.getProtocolFactory().addProtocol(protocol_config_ptr);
00614                         } catch (std::exception&) {
00615                             xmlFreeNodeList(protocol_config_ptr);
00616                             throw;
00617                         }
00618                         xmlFreeNodeList(protocol_config_ptr);
00619 
00620                         // send a 201 (created) response
00621                         response_ptr->setStatusCode(HTTPTypes::RESPONSE_CODE_CREATED);
00622                         response_ptr->setStatusMessage(HTTPTypes::RESPONSE_MESSAGE_CREATED);
00623 
00624                         // respond with the new Protocol's configuration
00625                         if (! cfg.getProtocolFactory().writeConfigXML(ss, protocol_id))
00626                             throw ProtocolFactory::ProtocolNotFoundException(protocol_id);
00627 
00628                     } else {
00629                         xmlFreeNodeList(protocol_config_ptr);
00630 
00631                         // Log an error and send a 403 (Forbidden) response.
00632                         std::string error_msg = "User doesn't have permission to create a Protocol.";
00633                         handleForbiddenRequest(request, tcp_conn, error_msg);
00634                         return;
00635                     }
00636                 } else {
00637                     // Log an error and send a 405 (Method Not Allowed) response.
00638                     handleMethodNotAllowed(request, tcp_conn, "GET, POST");
00639                     return;
00640                 }
00641 
00642             } else if (branches[1] == "plugins") {
00643 
00644                 // Send a list of all Protocols found in the UI directory
00645 
00646                 ConfigManager::writeBeginPionConfigXML(ss);
00647 
00648                 // Iterate through all the subdirectories of the Protocol directory (e.g. HTTPProtocol).
00649                 std::string protocol_directory = m_ui_directory + "/plugins/protocols";
00650                 boost::filesystem::directory_iterator end;
00651                 for (boost::filesystem::directory_iterator it(protocol_directory); it != end; ++it) {
00652                     if (boost::filesystem::is_directory(*it)) {
00653                         // Skip directories starting with a '.'.
00654                         if (it->path().leaf().substr(0, 1) == ".") continue;
00655 
00656                         ss << "<Protocol>"
00657                            << "<Plugin>" << it->path().leaf() << "</Plugin>"
00658                            << "</Protocol>";
00659                     }
00660                 }
00661 
00662                 ConfigManager::writeEndPionConfigXML(ss);
00663 
00664             } else if (branches.size() == 2) {
00665                 // branches[1] == protocol_id
00666 
00667                 if (request->getMethod() == HTTPTypes::REQUEST_METHOD_GET) {
00668                     // retrieve an existing Protocol's configuration
00669 
00670                     if (! cfg.getProtocolFactory().writeConfigXML(ss, branches[1]))
00671                         throw ProtocolFactory::ProtocolNotFoundException(branches[1]);
00672 
00673                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_PUT) {
00674                     // update existing Protocol's configuration
00675 
00676                     // convert request content into XML configuration info
00677                     xmlNodePtr protocol_config_ptr =
00678                         ProtocolFactory::createProtocolConfig(request->getContent(),
00679                                                               request->getContentLength());
00680 
00681                     // Check whether the User has permission to make the specified modification to the specified Protocol.
00682                     if (cfg.getUserManagerPtr()->updateAllowed(request->getUser(), cfg.getProtocolFactory(), branches[1], protocol_config_ptr)) {
00683                         try {
00684                             // push the new config into the ProtocolFactory
00685                             cfg.getProtocolFactory().setProtocolConfig(branches[1], protocol_config_ptr);
00686                         } catch (std::exception&) {
00687                             xmlFreeNodeList(protocol_config_ptr);
00688                             throw;
00689                         }
00690                         xmlFreeNodeList(protocol_config_ptr);
00691 
00692                         // respond with the Protocol's updated configuration
00693                         if (! cfg.getProtocolFactory().writeConfigXML(ss, branches[1]))
00694                             throw ProtocolFactory::ProtocolNotFoundException(branches[1]);
00695                     } else {
00696                         xmlFreeNodeList(protocol_config_ptr);
00697 
00698                         // Log an error and send a 403 (Forbidden) response.
00699                         std::string error_msg = "User doesn't have permission to modify Protocol " + branches[1] + ".";
00700                         handleForbiddenRequest(request, tcp_conn, error_msg);
00701                         return;
00702                     }
00703                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_DELETE) {
00704                     // delete an existing Protocol
00705 
00706                     // Check whether the User has permission to remove the specified Protocol.
00707                     if (cfg.getUserManagerPtr()->removalAllowed(request->getUser(), cfg.getProtocolFactory(), branches[1])) {
00708                         cfg.getProtocolFactory().removeProtocol(branches[1]);
00709 
00710                         // send a 204 (No Content) response
00711                         response_ptr->setStatusCode(HTTPTypes::RESPONSE_CODE_NO_CONTENT);
00712                         response_ptr->setStatusMessage(HTTPTypes::RESPONSE_MESSAGE_NO_CONTENT);
00713                     } else {
00714                         // Log an error and send a 403 (Forbidden) response.
00715                         std::string error_msg = "User doesn't have permission to delete Protocol " + branches[1] + ".";
00716                         handleForbiddenRequest(request, tcp_conn, error_msg);
00717                         return;
00718                     }
00719                 } else {
00720                     // Log an error and send a 405 (Method Not Allowed) response.
00721                     handleMethodNotAllowed(request, tcp_conn, "GET, PUT, DELETE");
00722                     return;
00723                 }
00724 
00725             } else {
00726                 // Log an error and send a 404 (Not Found) response.
00727                 handleNotFoundRequest(request, tcp_conn);
00728                 return;
00729             }
00730             //
00731             // END PROTOCOLS CONFIG
00732             //
00733         } else if (branches.front() == "reactors") {
00734             //
00735             // BEGIN REACTORS CONFIG
00736             //
00737             if (branches.size() == 1) {
00738                 if (request->getMethod() == HTTPTypes::REQUEST_METHOD_GET) {
00739 
00740                     // retrieve configuration for all Reactors
00741                     cfg.getReactionEngine().writeConfigXML(ss);
00742 
00743                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_POST) {
00744 
00745                     // add (create) a new Reactor
00746 
00747                     // convert request content into XML configuration info
00748                     xmlNodePtr reactor_config_ptr =
00749                         ReactionEngine::createReactorConfig(request->getContent(),
00750                                                             request->getContentLength());
00751 
00752                     // Check whether the User has permission to create the specified Reactor.
00753                     if (cfg.getUserManagerPtr()->creationAllowed(request->getUser(), cfg.getReactionEngine(), reactor_config_ptr)) {
00754                         // add the new Reactor to the ReactionEngine
00755                         std::string reactor_id;
00756                         try {
00757                             reactor_id = cfg.getReactionEngine().addReactor(reactor_config_ptr);
00758                         } catch (std::exception&) {
00759                             xmlFreeNodeList(reactor_config_ptr);
00760                             throw;
00761                         }
00762                         xmlFreeNodeList(reactor_config_ptr);
00763 
00764                         // send a 201 (created) response
00765                         response_ptr->setStatusCode(HTTPTypes::RESPONSE_CODE_CREATED);
00766                         response_ptr->setStatusMessage(HTTPTypes::RESPONSE_MESSAGE_CREATED);
00767 
00768                         // respond with the new Reactor's configuration
00769                         if (! cfg.getReactionEngine().writeConfigXML(ss, reactor_id))
00770                             throw ReactionEngine::ReactorNotFoundException(reactor_id);
00771 
00772                     } else {
00773                         xmlFreeNodeList(reactor_config_ptr);
00774 
00775                         // Log an error and send a 403 (Forbidden) response.
00776                         std::string error_msg = "User doesn't have permission to create the specified Reactor.";
00777                         handleForbiddenRequest(request, tcp_conn, error_msg);
00778                         return;
00779                     }
00780                 } else {
00781                     // Log an error and send a 405 (Method Not Allowed) response.
00782                     handleMethodNotAllowed(request, tcp_conn, "GET, POST");
00783                     return;
00784                 }
00785 
00786             } else if (branches[1] == "stats") {
00787 
00788                 // send statistics for all Reactors
00789                 cfg.getReactionEngine().writeStatsXML(ss);
00790 
00791             } else if (branches[1] == "plugins") {
00792 
00793                 // Send a list of all Reactors found in the UI directory
00794 
00795                 ConfigManager::writeBeginPionConfigXML(ss);
00796 
00797                 // Iterate through all the subdirectories of the Reactor directory (e.g. collection, processing, storage).
00798                 std::string reactor_directory = m_ui_directory + "/plugins/reactors";
00799                 boost::filesystem::directory_iterator end;
00800                 for (boost::filesystem::directory_iterator it(reactor_directory); it != end; ++it) {
00801                     if (boost::filesystem::is_directory(*it)) {
00802                         // Skip directories starting with a '.'.
00803                         if (it->path().leaf().substr(0, 1) == ".") continue;
00804 
00805                         // Iterate through all the subdirectories of the subdirectory (e.g. LogReactor).
00806                         boost::filesystem::directory_iterator end_2;
00807                         for (boost::filesystem::directory_iterator it2(*it); it2 != end_2; ++it2) {
00808                             if (boost::filesystem::is_directory(*it2)) {
00809                                 // Skip directories starting with a '.'.
00810                                 if (it2->path().leaf().substr(0, 1) == ".") continue;
00811 
00812                                 ss << "<Reactor>"
00813                                    << "<ReactorType>" << it->path().leaf() << "</ReactorType>"
00814                                    << "<Plugin>" << it2->path().leaf() << "</Plugin>"
00815                                    << "</Reactor>";
00816                             }
00817                         }
00818                     }
00819                 }
00820 
00821                 ConfigManager::writeEndPionConfigXML(ss);
00822 
00823             } else if (branches.size() == 2) {
00824                 // branches[1] == reactor_id (or possibly workspace_id, for GET or DELETE)
00825 
00826                 if (request->getMethod() == HTTPTypes::REQUEST_METHOD_GET) {
00827                     // retrieve an existing Reactor's configuration
00828 
00829                     if (! cfg.getReactionEngine().writeConfigXML(ss, branches[1])) {
00830                         // No Reactor found with that ID, so maybe it's a Workspace ID.
00831                         if (! cfg.getReactionEngine().writeWorkspaceLimitedConfigXML(ss, branches[1]))
00832                             throw ReactionEngine::ReactorNotFoundException(branches[1]);
00833                     }
00834 
00835                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_PUT) {
00836                     // update existing Reactor's configuration
00837 
00838                     // convert request content into XML configuration info
00839                     xmlNodePtr reactor_config_ptr =
00840                         ReactionEngine::createReactorConfig(request->getContent(),
00841                                                             request->getContentLength());
00842 
00843                     // Check whether the User has permission to make the specified modification to the specified Reactor.
00844                     if (cfg.getUserManagerPtr()->updateAllowed(request->getUser(), cfg.getReactionEngine(), branches[1], reactor_config_ptr)) {
00845                         try {
00846                             // push the new config into the ReactionEngine
00847                             cfg.getReactionEngine().setReactorConfig(branches[1], reactor_config_ptr);
00848                         } catch (std::exception&) {
00849                             xmlFreeNodeList(reactor_config_ptr);
00850                             throw;
00851                         }
00852                         xmlFreeNodeList(reactor_config_ptr);
00853 
00854                         // respond with the Reactor's updated configuration
00855                         if (! cfg.getReactionEngine().writeConfigXML(ss, branches[1]))
00856                             throw ReactionEngine::ReactorNotFoundException(branches[1]);
00857                     } else {
00858                         xmlFreeNodeList(reactor_config_ptr);
00859 
00860                         // Log an error and send a 403 (Forbidden) response.
00861                         std::string error_msg = "User doesn't have permission to modify Reactor " + branches[1] + ".";
00862                         handleForbiddenRequest(request, tcp_conn, error_msg);
00863                         return;
00864                     }
00865 
00866                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_DELETE) {
00867                     // delete an existing Reactor (or Reactors)
00868 
00869                     // Check whether the User has permission to remove the specified Reactor(s).
00870                     if (cfg.getUserManagerPtr()->removalAllowed(request->getUser(), cfg.getReactionEngine(), branches[1])) {
00871                         if (cfg.getReactionEngine().hasPlugin(branches[1])) {
00872                             cfg.getReactionEngine().removeReactor(branches[1]);
00873                         } else if (cfg.getReactionEngine().hasWorkspace(branches[1])) {
00874                             cfg.getReactionEngine().removeReactorsFromWorkspace(branches[1]);
00875                         } else
00876                             throw ReactionEngine::ReactorNotFoundException(branches[1]);
00877 
00878                         // send a 204 (No Content) response
00879                         response_ptr->setStatusCode(HTTPTypes::RESPONSE_CODE_NO_CONTENT);
00880                         response_ptr->setStatusMessage(HTTPTypes::RESPONSE_MESSAGE_NO_CONTENT);
00881                     } else {
00882                         // Log an error and send a 403 (Forbidden) response.
00883                         std::string error_msg = "User doesn't have permission to delete Reactors with the specified ID or Workspace ID: " + branches[1] + ".";
00884                         handleForbiddenRequest(request, tcp_conn, error_msg);
00885                         return;
00886                     }
00887                 } else {
00888                     // Log an error and send a 405 (Method Not Allowed) response.
00889                     handleMethodNotAllowed(request, tcp_conn, "GET, PUT, DELETE");
00890                     return;
00891                 }
00892 
00893             } else if (branches.size() == 3) {
00894                 // branches[1] == reactor_id
00895 
00896                 if (branches[2] == "start") {
00897 
00898                     // start a Reactor
00899                     cfg.getReactionEngine().startReactor(branches[1]);
00900 
00901                     // respond by sending all the Reactor stats
00902                     cfg.getReactionEngine().writeStatsXML(ss);
00903 
00904                 } else if (branches[2] == "stop") {
00905 
00906                     // stop a Reactor
00907                     cfg.getReactionEngine().stopReactor(branches[1]);
00908 
00909                     // respond by sending all the Reactor stats
00910                     cfg.getReactionEngine().writeStatsXML(ss);
00911 
00912                 } else if (branches[2] == "move") {
00913                     if (request->getMethod() == HTTPTypes::REQUEST_METHOD_PUT) {
00914                         // update the specified Reactor's configuration (only UI location settings)
00915 
00916                         // convert request content into XML configuration info
00917                         xmlNodePtr reactor_config_ptr =
00918                             ReactionEngine::createReactorConfig(request->getContent(),
00919                                                                 request->getContentLength());
00920 
00921                         try {
00922                             // push the new config settings into the ReactionEngine
00923                             cfg.getReactionEngine().setReactorLocation(branches[1], reactor_config_ptr);
00924                         } catch (std::exception&) {
00925                             xmlFreeNodeList(reactor_config_ptr);
00926                             throw;
00927                         }
00928                         xmlFreeNodeList(reactor_config_ptr);
00929 
00930                         // respond with the Reactor's updated configuration
00931                         if (! cfg.getReactionEngine().writeConfigXML(ss, branches[1]))
00932                             throw ReactionEngine::ReactorNotFoundException(branches[1]);
00933                     } else {
00934                         // Log an error and send a 405 (Method Not Allowed) response.
00935                         handleMethodNotAllowed(request, tcp_conn, "PUT");
00936                         return;
00937                     }
00938                 } else {
00939                     // Log an error and send a 404 (Not Found) response.
00940                     handleNotFoundRequest(request, tcp_conn);
00941                     return;
00942                 }
00943             } else {
00944                 // Log an error and send a 404 (Not Found) response.
00945                 handleNotFoundRequest(request, tcp_conn);
00946                 return;
00947             }
00948             //
00949             // END REACTORS CONFIG
00950             //
00951         } else if (branches.front() == "connections") {
00952             //
00953             // BEGIN CONNECTIONS CONFIG
00954             //
00955             if (branches.size() == 1) {
00956                 if (request->getMethod() == HTTPTypes::REQUEST_METHOD_GET) {
00957 
00958                     // retrieve configuration for all Reactor connections
00959                     cfg.getReactionEngine().writeConnectionsXML(ss);
00960 
00961                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_POST) {
00962 
00963                     // create a new Reactor connection
00964 
00965                     // convert request content into XML configuration info
00966                     xmlNodePtr connection_config_ptr = 
00967                         ReactionEngine::createConnectionConfig(request->getContent(), request->getContentLength());
00968 
00969                     // Check whether the User has permission to create the specified Reactor connection.
00970                     if (cfg.getUserManagerPtr()->creationAllowed(request->getUser(), cfg.getReactionEngine(), connection_config_ptr)) {
00971                         // create a new Reactor connection
00972                         std::string connection_id = cfg.getReactionEngine().addReactorConnection(connection_config_ptr);
00973 
00974                         // send a 201 (Created) response
00975                         response_ptr->setStatusCode(HTTPTypes::RESPONSE_CODE_CREATED);
00976                         response_ptr->setStatusMessage(HTTPTypes::RESPONSE_MESSAGE_CREATED);
00977 
00978                         // respond with the new connection's configuration
00979                         cfg.getReactionEngine().writeConnectionsXML(ss, connection_id);
00980 
00981                     } else {
00982                         // Log an error and send a 403 (Forbidden) response.
00983                         std::string error_msg = "User doesn't have permission to create the specified Reactor connection.";
00984                         handleForbiddenRequest(request, tcp_conn, error_msg);
00985                         return;
00986                     }
00987                 } else {
00988                     // Log an error and send a 405 (Method Not Allowed) response.
00989                     handleMethodNotAllowed(request, tcp_conn, "GET, POST");
00990                     return;
00991                 }
00992 
00993             } else {
00994                 // branches[1] == connection_id
00995 
00996                 if (request->getMethod() == HTTPTypes::REQUEST_METHOD_GET) {
00997 
00998                     // retrieve configuration for specific Reactor connections
00999                     cfg.getReactionEngine().writeConnectionsXML(ss, branches[1]);
01000 
01001                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_DELETE) {
01002 
01003                     // remove an existing Reactor connection
01004 
01005                     // Check whether the User has permission to remove the specified connection.
01006                     if (cfg.getUserManagerPtr()->removalAllowed(request->getUser(), cfg.getReactionEngine(), branches[1])) {
01007                         cfg.getReactionEngine().removeReactorConnection(branches[1]);
01008 
01009                         // send a 204 (No Content) response
01010                         response_ptr->setStatusCode(HTTPTypes::RESPONSE_CODE_NO_CONTENT);
01011                         response_ptr->setStatusMessage(HTTPTypes::RESPONSE_MESSAGE_NO_CONTENT);
01012                     } else {
01013                         // Log an error and send a 403 (Forbidden) response.
01014                         std::string error_msg = "User doesn't have permission to delete connection " + branches[1] + ".";
01015                         handleForbiddenRequest(request, tcp_conn, error_msg);
01016                         return;
01017                     }
01018                 } else {
01019                     // Log an error and send a 405 (Method Not Allowed) response.
01020                     handleMethodNotAllowed(request, tcp_conn, "GET, DELETE");
01021                     return;
01022                 }
01023             }
01024             //
01025             // END CONNECTIONS CONFIG
01026             //
01027         } else if (branches.front() == "workspaces") {
01028             //
01029             // BEGIN WORKSPACES CONFIG
01030             //
01031             if (branches.size() == 1) {
01032                 if (request->getMethod() == HTTPTypes::REQUEST_METHOD_GET) {
01033 
01034                     // retrieve configuration for all Reactor Workspaces
01035                     cfg.getReactionEngine().writeWorkspacesXML(ss);
01036 
01037                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_POST) {
01038 
01039                     // add (create) a new Reactor Workspace
01040 
01041                     // Check whether the User has permission to create a Reactor Workspace.
01042                     if (cfg.getUserManagerPtr()->creationAllowed(request->getUser(), cfg.getReactionEngine(), NULL)) {
01043                         // create a new Reactor Workspace
01044                         std::string workspace_id = cfg.getReactionEngine().addWorkspace(request->getContent(),
01045                                                                                         request->getContentLength());
01046                         // send a 201 (Created) response
01047                         response_ptr->setStatusCode(HTTPTypes::RESPONSE_CODE_CREATED);
01048                         response_ptr->setStatusMessage(HTTPTypes::RESPONSE_MESSAGE_CREATED);
01049 
01050                         // respond with the new Reactor Workspace's configuration
01051                         cfg.getReactionEngine().writeWorkspaceXML(ss, workspace_id);
01052 
01053                     } else {
01054                         // Log an error and send a 403 (Forbidden) response.
01055                         std::string error_msg = "User doesn't have permission to create a Reactor Workspace.";
01056                         handleForbiddenRequest(request, tcp_conn, error_msg);
01057                         return;
01058                     }
01059                 } else {
01060                     // Log an error and send a 405 (Method Not Allowed) response.
01061                     handleMethodNotAllowed(request, tcp_conn, "GET, POST");
01062                     return;
01063                 }
01064 
01065             } else {
01066                 // branches[1] == workspace_id
01067 
01068                 if (request->getMethod() == HTTPTypes::REQUEST_METHOD_GET) {
01069 
01070                     // retrieve configuration for the specified Reactor Workspace
01071                     cfg.getReactionEngine().writeWorkspaceXML(ss, branches[1]);
01072 
01073                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_PUT) {
01074                     // update existing Reactor Workspace's configuration
01075 
01076                     // Check whether the User has permission to modify the specified Workspace.
01077                     if (cfg.getUserManagerPtr()->updateAllowed(request->getUser(), cfg.getReactionEngine(), branches[1], NULL)) {
01078                         // push the new config into the ReactionEngine
01079                         cfg.getReactionEngine().setWorkspaceConfig(branches[1], request->getContent(),
01080                                                                    request->getContentLength());
01081 
01082                         // respond with the Workspace's updated configuration
01083                         cfg.getReactionEngine().writeWorkspaceXML(ss, branches[1]);
01084 
01085                     } else {
01086                         // Log an error and send a 403 (Forbidden) response.
01087                         std::string error_msg = "User doesn't have permission to modify Workspace " + branches[1] + ".";
01088                         handleForbiddenRequest(request, tcp_conn, error_msg);
01089                         return;
01090                     }
01091 
01092                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_DELETE) {
01093 
01094                     // remove an existing empty Reactor Workspace
01095 
01096                     // Check whether the User has permission to remove the specified Workspace.
01097                     if (cfg.getUserManagerPtr()->removalAllowed(request->getUser(), cfg.getReactionEngine(), branches[1])) {
01098                         cfg.getReactionEngine().removeWorkspace(branches[1]);
01099 
01100                         // send a 204 (No Content) response
01101                         response_ptr->setStatusCode(HTTPTypes::RESPONSE_CODE_NO_CONTENT);
01102                         response_ptr->setStatusMessage(HTTPTypes::RESPONSE_MESSAGE_NO_CONTENT);
01103                     } else {
01104                         // Log an error and send a 403 (Forbidden) response.
01105                         std::string error_msg = "User doesn't have permission to delete Workspace " + branches[1] + ".";
01106                         handleForbiddenRequest(request, tcp_conn, error_msg);
01107                         return;
01108                     }
01109 
01110                 } else {
01111                     // Log an error and send a 405 (Method Not Allowed) response.
01112                     handleMethodNotAllowed(request, tcp_conn, "GET, PUT, DELETE");
01113                     return;
01114                 }
01115             }
01116             //
01117             // END WORKSPACES CONFIG
01118             //
01119         } else if (branches.front() == "servers") {
01120             //
01121             // BEGIN SERVERS CONFIG
01122             //
01123             if (branches.size() == 1) {
01124                 if (request->getMethod() == HTTPTypes::REQUEST_METHOD_GET) {
01125 
01126                     // retrieve configuration for all Servers
01127                     cfg.getServiceManager().writeServersXML(ss);
01128 
01129                 } else {
01130                     // Log an error and send a 405 (Method Not Allowed) response.
01131                     handleMethodNotAllowed(request, tcp_conn, "GET");
01132                     return;
01133                 }
01134             } else if (branches.size() == 2) {
01135                 // branches[1] == server_id
01136 
01137                 if (request->getMethod() == HTTPTypes::REQUEST_METHOD_GET) {
01138                     // retrieve an existing Server's configuration
01139                     if (! cfg.getServiceManager().writeServerXML(ss, branches[1]))
01140                         throw PionPlugin::PluginNotFoundException(branches[1]);
01141 
01142                 } else {
01143                     // Log an error and send a 405 (Method Not Allowed) response.
01144                     handleMethodNotAllowed(request, tcp_conn, "GET");
01145                     return;
01146                 }
01147 
01148             } else {
01149                 // Log an error and send a 404 (Not Found) response.
01150                 handleNotFoundRequest(request, tcp_conn);
01151                 return;
01152             }
01153             //
01154             // END SERVERS CONFIG
01155             //
01156         } else if (branches.front() == "services") {
01157             //
01158             // BEGIN SERVICES CONFIG
01159             //
01160             if (branches.size() == 1) {
01161                 if (request->getMethod() == HTTPTypes::REQUEST_METHOD_GET) {
01162 
01163                     // retrieve configuration for all PlatformServices
01164                     getServiceManager().writeConfigXML(ss);
01165 
01166                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_POST) {
01167 
01168                     // add (create) a new PlatformService
01169 
01170                     // convert request content into XML configuration info
01171                     xmlNodePtr service_config_ptr =
01172                         ServiceManager::createPlatformServiceConfig(request->getContent(),
01173                                                                     request->getContentLength());
01174 
01175                     // Check whether the User has permission to create the specified PlatformService.
01176                     if (cfg.getUserManagerPtr()->creationAllowed(request->getUser(), cfg.getServiceManager(), service_config_ptr)) {
01177                         // add the new PlatformService to the ServiceManager
01178                         std::string service_id;
01179                         try {
01180                             service_id = getServiceManager().addPlatformService(service_config_ptr);
01181                         } catch (std::exception&) {
01182                             xmlFreeNodeList(service_config_ptr);
01183                             throw;
01184                         }
01185                         xmlFreeNodeList(service_config_ptr);
01186 
01187                         // send a 201 (created) response
01188                         response_ptr->setStatusCode(HTTPTypes::RESPONSE_CODE_CREATED);
01189                         response_ptr->setStatusMessage(HTTPTypes::RESPONSE_MESSAGE_CREATED);
01190 
01191                         // respond with the new PlatformService's configuration
01192                         if (! getServiceManager().writeConfigXML(ss, service_id))
01193                             throw ServiceManager::PlatformServiceNotFoundException(service_id);
01194 
01195                     } else {
01196                         xmlFreeNodeList(service_config_ptr);
01197 
01198                         // Log an error and send a 403 (Forbidden) response.
01199                         std::string error_msg = "User doesn't have permission to create the specified PlatformService.";
01200                         handleForbiddenRequest(request, tcp_conn, error_msg);
01201                         return;
01202                     }
01203                 } else {
01204                     // Log an error and send a 405 (Method Not Allowed) response.
01205                     handleMethodNotAllowed(request, tcp_conn, "GET, POST");
01206                     return;
01207                 }
01208 
01209             } else if (branches[1] == "plugins") {
01210 
01211                 // Send a list of all Services found in the UI directory
01212 
01213                 ConfigManager::writeBeginPionConfigXML(ss);
01214 
01215                 // Iterate through all the subdirectories of the Service directory.
01216                 std::string service_directory = m_ui_directory + "/plugins/services";
01217                 boost::filesystem::directory_iterator end;
01218                 for (boost::filesystem::directory_iterator it(service_directory); it != end; ++it) {
01219                     if (boost::filesystem::is_directory(*it)) {
01220                         // Skip directories starting with a '.'.
01221                         if (it->path().leaf().substr(0, 1) == ".") continue;
01222 
01223                         ss << "<Service>"
01224                            << "<Plugin>" << it->path().leaf() << "</Plugin>"
01225                            << "</Service>";
01226                     }
01227                 }
01228 
01229                 ConfigManager::writeEndPionConfigXML(ss);
01230 
01231             } else if (branches.size() == 2) {
01232                 // branches[1] == service_id
01233 
01234                 if (request->getMethod() == HTTPTypes::REQUEST_METHOD_GET) {
01235                     // retrieve an existing PlatformService's configuration
01236 
01237                     if (! getServiceManager().writeConfigXML(ss, branches[1]))
01238                         throw ServiceManager::PlatformServiceNotFoundException(branches[1]);
01239 
01240                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_DELETE) {
01241                     // delete an existing PlatformService
01242 
01243                     // Check whether the User has permission to remove the specified PlatformService.
01244                     if (cfg.getUserManagerPtr()->removalAllowed(request->getUser(), cfg.getServiceManager(), branches[1])) {
01245                         getServiceManager().removePlatformService(branches[1]);
01246 
01247                         // send a 204 (No Content) response
01248                         response_ptr->setStatusCode(HTTPTypes::RESPONSE_CODE_NO_CONTENT);
01249                         response_ptr->setStatusMessage(HTTPTypes::RESPONSE_MESSAGE_NO_CONTENT);
01250                     } else {
01251                         // Log an error and send a 403 (Forbidden) response.
01252                         std::string error_msg = "User doesn't have permission to delete PlatformService " + branches[1] + ".";
01253                         handleForbiddenRequest(request, tcp_conn, error_msg);
01254                         return;
01255                     }
01256                 } else {
01257                     // Log an error and send a 405 (Method Not Allowed) response.
01258                     handleMethodNotAllowed(request, tcp_conn, "GET, DELETE");
01259                     return;
01260                 }
01261 
01262             } else {
01263                 // Log an error and send a 404 (Not Found) response.
01264                 handleNotFoundRequest(request, tcp_conn);
01265                 return;
01266             }
01267             //
01268             // END SERVICES CONFIG
01269             //
01270         } else if (branches.front() == "users") {
01271             //
01272             // BEGIN USERS CONFIG
01273             //
01274             if (branches.size() == 1) {
01275                 if (request->getMethod() == HTTPTypes::REQUEST_METHOD_GET) {
01276 
01277                     // retrieve configuration for all Users
01278                     cfg.getUserManagerPtr()->writeConfigXML(ss);
01279 
01280                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_POST) {
01281 
01282                     // add (create) a new user
01283 
01284                     // convert request content into XML configuration info
01285                     std::string user_id;
01286                     xmlNodePtr user_config_ptr = UserManager::createUserConfig(user_id,
01287                                                                                request->getContent(),
01288                                                                                request->getContentLength());
01289 
01290                     // Check whether the User has permission to create new Users.
01291                     if (cfg.getUserManagerPtr()->creationAllowed(request->getUser(), *cfg.getUserManagerPtr(), NULL)) {
01292                         // add the new User to the UserManager
01293                         try {
01294                             user_id = cfg.getUserManagerPtr()->addUser(user_id, user_config_ptr);
01295                         } catch (std::exception&) {
01296                             xmlFreeNodeList(user_config_ptr);
01297                             throw;
01298                         }
01299                         xmlFreeNodeList(user_config_ptr);
01300 
01301                         // send a 201 (Created) response
01302                         response_ptr->setStatusCode(HTTPTypes::RESPONSE_CODE_CREATED);
01303                         response_ptr->setStatusMessage(HTTPTypes::RESPONSE_MESSAGE_CREATED);
01304 
01305                         // respond with the new User's configuration
01306                         if (! cfg.getUserManagerPtr()->writeConfigXML(ss, user_id))
01307                             throw UserManager::UserNotFoundException(user_id);
01308                     } else {
01309                         xmlFreeNodeList(user_config_ptr);
01310 
01311                         // Log an error and send a 403 (Forbidden) response.
01312                         std::string error_msg = "User doesn't have permission to create a User.";
01313                         handleForbiddenRequest(request, tcp_conn, error_msg);
01314                         return;
01315                     }
01316                 } else {
01317                     // Log an error and send a 405 (Method Not Allowed) response.
01318                     handleMethodNotAllowed(request, tcp_conn, "GET, POST");
01319                     return;
01320                 }
01321 
01322             } else {
01323                 // branches[1] == user_id
01324 
01325                 if (request->getMethod() == HTTPTypes::REQUEST_METHOD_GET) {
01326 
01327                     // retrieve configuration for specific User
01328                     cfg.getUserManagerPtr()->writeConfigXML(ss, branches[1]);
01329 
01330                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_PUT) {
01331                     // update existing User's configuration
01332 
01333                     // convert request content into XML configuration info
01334                     std::string user_id; // should be assigned empty string on the next line, ignored in any case
01335                     xmlNodePtr user_config_ptr = UserManager::createUserConfig(user_id,
01336                                                                                request->getContent(),
01337                                                                                request->getContentLength());
01338 
01339                     // Check whether the User has permission to modify the specified User.
01340                     if (cfg.getUserManagerPtr()->updateAllowed(request->getUser(), *cfg.getUserManagerPtr(), branches[1], NULL)) {
01341                         // push the new config into the UserManager
01342                         try {
01343                             cfg.getUserManagerPtr()->setUserConfig(branches[1], user_config_ptr);
01344                         } catch (std::exception&) {
01345                             xmlFreeNodeList(user_config_ptr);
01346                             throw;
01347                         }
01348                         xmlFreeNodeList(user_config_ptr);
01349 
01350                         // respond with the new User's configuration
01351                         if (! cfg.getUserManagerPtr()->writeConfigXML(ss, branches[1]))
01352                             throw UserManager::UserNotFoundException(branches[1]);
01353 
01354                     } else {
01355                         // Log an error and send a 403 (Forbidden) response.
01356                         std::string error_msg = "User doesn't have permission to modify User " + branches[1] + ".";
01357                         handleForbiddenRequest(request, tcp_conn, error_msg);
01358                         return;
01359                     }
01360                 } else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_DELETE) {
01361 
01362                     // remove an existing User
01363 
01364                     // Check whether the User has permission to remove the specified User.
01365                     if (cfg.getUserManagerPtr()->removalAllowed(request->getUser(), *cfg.getUserManagerPtr(), branches[1])) {
01366                         cfg.getUserManagerPtr()->removeUser(branches[1]);
01367 
01368                         // send a 204 (No Content) response
01369                         response_ptr->setStatusCode(HTTPTypes::RESPONSE_CODE_NO_CONTENT);
01370                         response_ptr->setStatusMessage(HTTPTypes::RESPONSE_MESSAGE_NO_CONTENT);
01371                     } else {
01372                         // Log an error and send a 403 (Forbidden) response.
01373                         std::string error_msg = "User doesn't have permission to delete User " + branches[1] + ".";
01374                         handleForbiddenRequest(request, tcp_conn, error_msg);
01375                         return;
01376                     }
01377                 } else {
01378                     // Log an error and send a 405 (Method Not Allowed) response.
01379                     handleMethodNotAllowed(request, tcp_conn, "GET, PUT, DELETE");
01380                     return;
01381                 }
01382             }
01383             //
01384             // END USERS CONFIG
01385             //
01386         } else if (branches.front() == "plugins") {
01387 
01388             // Send a list of all Plugins found in the Plugin directories.
01389 
01390             ConfigManager::writeBeginPionConfigXML(ss);
01391 
01392             std::vector<std::string> plugins;
01393             PionPlugin::getAllPluginNames(plugins);
01394             for (std::vector<std::string>::iterator i = plugins.begin(); i != plugins.end(); ++i) {
01395                 ss << "<Plugin>" << *i << "</Plugin>";
01396             }
01397 
01398             ConfigManager::writeEndPionConfigXML(ss);
01399 
01400         } else if (branches.front() == "dbengines") {
01401 
01402             // Send configuration of all database engines.
01403 
01404             cfg.getDatabaseManager().writeDatabaseEnginesXML(ss);
01405 
01406         } else {
01407             // Log an error and send a 404 (Not Found) response.
01408             handleNotFoundRequest(request, tcp_conn);
01409             return;
01410         }
01411     } catch (std::exception&) {
01412         // This exception will be caught by HTTPServer::handleRequest(), which will log the error and
01413         // send a 500 (Server Error) response, so all we need to do here is log the request, if needed.
01414         logRequestIfPotentialConfigChange(request, HTTPTypes::RESPONSE_CODE_SERVER_ERROR);
01415         throw;
01416     }
01417 
01418     logRequestIfPotentialConfigChange(request, response_ptr->getStatusCode());
01419 
01420     // prepare the writer object for XML output
01421     HTTPResponseWriterPtr writer(HTTPResponseWriter::create(tcp_conn, response_ptr,
01422                                                             boost::bind(&TCPConnection::finish, tcp_conn)));
01423     writer->getResponse().setContentType(HTTPTypes::CONTENT_TYPE_XML);
01424 
01425     // send the response
01426     writer->write(ss.str());
01427     writer->send();
01428 }
01429 
01430 void ConfigService::handleBadRequest(HTTPRequestPtr& request, TCPConnectionPtr& tcp_conn, const std::string& error_msg) {
01431     PlatformService::handleBadRequest(request, tcp_conn, error_msg);
01432     logRequestIfPotentialConfigChange(request, HTTPTypes::RESPONSE_CODE_BAD_REQUEST);
01433 }
01434 
01435 void ConfigService::handleForbiddenRequest(HTTPRequestPtr& request, TCPConnectionPtr& tcp_conn, const std::string& error_msg) {
01436     PlatformService::handleForbiddenRequest(request, tcp_conn, error_msg);
01437     logRequestIfPotentialConfigChange(request, HTTPTypes::RESPONSE_CODE_FORBIDDEN);
01438 }
01439 
01440 void ConfigService::handleNotFoundRequest(HTTPRequestPtr& request, TCPConnectionPtr& tcp_conn) {
01441     PlatformService::handleNotFoundRequest(request, tcp_conn);
01442     logRequestIfPotentialConfigChange(request, HTTPTypes::RESPONSE_CODE_NOT_FOUND);
01443 }
01444 
01445 void ConfigService::handleMethodNotAllowed(HTTPRequestPtr& request, TCPConnectionPtr& tcp_conn, const std::string& allowed_methods) {
01446     PlatformService::handleMethodNotAllowed(request, tcp_conn, allowed_methods);
01447     logRequestIfPotentialConfigChange(request, HTTPTypes::RESPONSE_CODE_METHOD_NOT_ALLOWED);
01448 }
01449 
01450 void ConfigService::logRequestIfPotentialConfigChange(HTTPRequestPtr& request, unsigned int status) {
01451     // In ConfigService, all GET requests that are handled leave the configuration unchanged.
01452     if (request->getMethod() != HTTPTypes::REQUEST_METHOD_GET) {
01453         std::string content(request->getContent(), request->getContentLength()); // Could be empty.
01454         std::string user(request->getUser() ? request->getUser()->getUsername() : "NONE");
01455         PION_LOG_INFO(m_config_logger, request->getMethod() 
01456                                         << ' ' << status
01457                                         << ' ' << user
01458                                         << ' ' << request->getResource() << ' ' << content);
01459     }
01460 }
01461 
01462 }   // end namespace plugins
01463 }   // end namespace pion
01464 
01465 
01467 extern "C" PION_PLUGIN_API pion::server::PlatformService *pion_create_ConfigService(void) {
01468     return new pion::plugins::ConfigService();
01469 }
01470 
01472 extern "C" PION_PLUGIN_API void pion_destroy_ConfigService(pion::plugins::ConfigService *service_ptr) {
01473     delete service_ptr;
01474 }

Generated on Wed Apr 13 16:38:34 2011 for pion-platform by  doxygen 1.4.7