/** @class gatsDBpp::DatabaseHandles @brief Employs the DatabaseHandles methods. These routines establish and provide access to the database connections that are usually established when the program initializes. @date $Date$ @version $Rev$ @author - Lance Deaver @copyright (©) Copyright 2006 by GATS Inc. 11864 Canon Blvd., Suite 101, Newport News, VA 23606 All Rights Reserved. No part of this software or publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or otherwise without the prior written permission of GATS Inc. @see gatsDBpp::DatabaseHandles.h @see gatsDBpp::GATS_DB @bug None known $Id$ */ #include "DatabaseHandles.h" #include "CMarkup.h" #include "GATS_Utilities.hpp" #include "GATS_DB_mysql.h" #include "DBTable.h" #include "GATS_DB_Exception.h" using namespace GATS_Utilities; using namespace gatsDBpp; DatabaseHandles::DatabaseHandles() { } DatabaseHandles::~DatabaseHandles() { } /** * This function will add a GATS_DB database handle to the DatabaseHandles class and reference * that connection to the provided string connectionName. If this class already has * a connection referenced by the connectionName this class does nothing. * * @param[in] connectionName A string that is used to reference the GATS_DB connection handle. * @param[in] dbhandle A GATS_DB handle to be added to the internal map. */ void DatabaseHandles::Add(const std::string& connectionName,GATS_DBptr dbhandle) { if(! HandleExists(connectionName) ) _DBMap[connectionName] = dbhandle; } /** * Return a GATS_DBptr pointer to the requested database handle. If the requested name is not * found this method will return a NULL GATS_DBptr. * * @param[in] connectionName The string name for the GATS_DB database handle. * @retval gatsDBpp::GATS_DBptr The database handle as a smart pointer. */ GATS_DBptr DatabaseHandles::Get(const std::string& connectionName) { return (HandleExists(connectionName) ) ? _DBMap[connectionName] : GATS_DBptr() ; } /** * Remove the database handle with the specified connectionName. If the requested name is not * found the method does nothing. * * @param[in] connectionName The string name for the GATS_DB database handle. */ void DatabaseHandles::Remove(const std::string& connectionName) { std::map::iterator mapIter= _DBMap.find(connectionName); if (mapIter != _DBMap.end() ) _DBMap.erase(mapIter); } void DatabaseHandles::KillAll() { _DBMap.clear(); } /** * Return the number of GATS_DB connections contained in this class. * @retval int The number of connections contained in this class. */ int DatabaseHandles::NumberOfHandles() const { return static_cast(_DBMap.size() ); } /** * Indicates if a handle with a specified name exists in this class. Returns true * if this connectionName is found. * * @param[in] connectionName The string name for the GATS_DB database handle. * @retval bool A true/false value indicating if the connectionName is found in the class. */ bool DatabaseHandles::HandleExists(const std::string& connectionName) const { std::map::const_iterator mapIter= _DBMap.find(connectionName); return (mapIter != _DBMap.end() ) ; } /** * Returns a list of the database connection string names. * * @retval std::vector A list of the string names of the database connection handles that are in this class. */ std::vector DatabaseHandles::GetHandleNames() const { std::vector names; for(std::map::const_iterator mapIter=_DBMap.begin(); mapIter != _DBMap.end(); ++mapIter ) names.push_back(mapIter->first); return names; } void DatabaseHandles::InitTables(CMarkup* xml, const bool clearit ) { std::string Version = xml->GetAttrib("version").c_str(); assert( ! Version.empty() && ConvertFromString(Version, std::scientific) >= 0.1) ; if(clearit) { _TableMap.clear(); } xml->IntoElem(); // step into the element while(xml->FindElem() ) { if(strcasecmp(xml->GetTagName().c_str(), "table") ==0 ) { std::string tableName = xml->GetAttrib("name").c_str() ; assert( ! tableName.empty() ); std::string typeName = xml->GetAttrib("type").c_str() ; assert( ! typeName.empty() ); xml->IntoElem() ; std::string dbname; std::map tableFields; while( xml->FindElem() ) { if(strcasecmp(xml->GetTagName().c_str(), "dbName") ==0 ) { dbname= CMarkup::TrimString(xml->GetData() ); } else if(strcasecmp(xml->GetTagName().c_str(), "fields") ==0 ) { while(xml->FindChildElem() ) { if(strcasecmp(xml->GetChildTagName().c_str(), "field") !=0 ) continue; std::string idName = xml->GetChildAttrib("id").c_str(); if(idName.empty() ) continue; std::string fieldName = CMarkup::TrimString( xml->GetChildData() ) ; tableFields[idName] = (fieldName.empty() ) ? idName : fieldName ; } } } _TableMap[tableName] = DBTable_ptr(new DBTable(tableName, tableFields, dbname, typeName) ); xml->OutOfElem(); } } // end while over database connections xml->OutOfElem(); } /** * This routine will parse the parameters from an XML stream and establish any * requested database connections. An additional parameter will cause the * class to clear any already established connections before parsing this data. * * @param[in] xml A pointer to a CMarkup instance that has the internal * position set to the databaseConnections tag. * @param[in] clearit A boolean that will indicate if any previously * established connections will be removed before parsing the * XML stream default value is true. * * @todo Add an exception throw if database type is unknown. * @todo Remove assert convert to exception. */ void DatabaseHandles::Init( CMarkup* xml, const bool clearit ) { std::string Version = xml->GetAttrib("version").c_str(); assert( ! Version.empty() && ConvertFromString(Version, std::scientific) >= 0.1) ; if(clearit) { _DBMap.clear(); } xml->IntoElem(); // step into the element while(xml->FindElem() ) { std::string DBConnectionName; if(strcasecmp(xml->GetTagName().c_str(), "connection") ==0 ) { DBConnectionName = xml->GetAttrib("name").c_str() ; assert( ! DBConnectionName.empty() ); if( strcmp(xml->GetAttrib("connect").c_str(), "true" ) != 0 ) continue; } std::string username, password, hostname, dbname, dbtype; std::vector ports; unsigned int defaultPortNo=0 ; while(xml->FindChildElem() ) { std::string tagName = xml->GetChildTagName() ; std::string dataValue = CMarkup::TrimString(xml->GetChildData() ); if( strcasecmp( tagName.c_str(), "userName") ==0 && username.empty() ) { username = dataValue; } else if (strcasecmp( tagName.c_str(), "password") == 0 && password.empty() ) { password = dataValue; } else if (strcasecmp( tagName.c_str(), "serverName") == 0 && hostname.empty() ) { std::string Port = xml->GetChildAttrib("port").c_str(); if( ! Port.empty() ) { ports.push_back(ConvertFromString(Port, std::dec, false) ); } hostname = dataValue; } else if (strcasecmp( tagName.c_str(), "dbName") == 0 && dbname.empty() ) { //initial database name dbname = dataValue; } else if (strcasecmp( tagName.c_str(), "type") == 0 && dbtype.empty() ) { // the database type add new ones here if (strcasecmp( dataValue.c_str(), "mysql") == 0) { dbtype = std::string("mysql"); } } } //end while child elements if(dbtype == std::string("mysql") ) { if( hostname.empty() ) { hostname=std::string("localhost"); // a default server } defaultPortNo=0; _DBMap[DBConnectionName] = GATS_DBptr( new GATS_DB_mysql(username.c_str(), password.c_str(), dbname.c_str() , hostname.c_str(), ( ports.empty() ) ? defaultPortNo : ports.front() )) ; } else { std::string msg = dbtype + " is not a recognized Database type"; THROW_GATS_EXCEPTION( UnknownDatabaseType, msg.c_str() ); } } // end while over database connections xml->OutOfElem() ; } /** * This function will create a static DatabaseHandles instance and return a * pointer to that instance. This is a way using * global data in a sort of safe manner and it is used to provide * database access to a module without having to pass in all the * handle information. * * @retval gatsDBpp::DatabaseHandles* A pointer to the internal instance. */ DatabaseHandles* gatsDBpp::GetDatabaseHandles() { static std::auto_ptr handlePtr(new DatabaseHandles() ); return handlePtr.get(); }