00001 // ******************************************************************* 00002 // Server.cpp 00003 // ******************************************************************* 00004 // 00005 // DESCRIPTION: API for Server class. Used by Broker of the 00006 // DocConversion project to broker a conversion 00007 // of a given document. 00008 // NOTE: This program makes use of strings and Server.h. 00009 // 00010 /*************************************************************************** 00011 * Copyright (C) 2003 by drs. Eric D. Schabell * 00012 * erics@cs.kun.nl * 00013 * * 00014 * This program is free software; you can redistribute it and/or modify * 00015 * it under the terms of the GNU General Public License as published by * 00016 * the Free Software Foundation; either version 2 of the License, or * 00017 * (at your option) any later version. * 00018 ***************************************************************************/ 00019 00020 //-------------------------------------------------------------------- 00021 //#includes 00022 //-------------------------------------------------------------------- 00023 #include <iostream> 00024 #include <string> 00025 #include <fstream> 00026 #include "Server.h" 00027 #include "Document.h" 00028 #include <pqxx/all.h> // postgresql api. 00029 00030 using namespace std; 00031 using namespace pqxx; 00032 00033 //-------------------------------------------------------------------- 00034 //Variables 00035 //-------------------------------------------------------------------- 00036 const string DEFAULT_ADDRESS = "127.0.0.1"; // default value. 00037 00038 //-------------------------------------------------------------------- 00039 //Purpose: Default constructor. 00040 //Preconditions: none. 00041 //Postconditions: Server object created and exists set to true. 00042 //Arguments: none. 00043 //Returns: 0. 00044 //Called Funcs: none. 00045 //-------------------------------------------------------------------- 00046 Server::Server() 00047 { 00048 serverAddress = DEFAULT_ADDRESS; 00049 return; 00050 } 00051 00052 //-------------------------------------------------------------------- 00053 //Purpose: Constructo with server address. 00054 //Preconditions: none.. 00055 //Postconditions: Server object created, serverAddress set and 00056 // exists set to true. 00057 //Arguments: string address. 00058 //Returns: 0. 00059 //Called Funcs: none. 00060 //-------------------------------------------------------------------- 00061 Server::Server( string address ) 00062 { 00063 serverAddress = address; 00064 return; 00065 } 00066 00067 //-------------------------------------------------------------------- 00068 //Purpose: Destructor. 00069 //Preconditions: Server object exists.. 00070 //Postconditions: Server object destroyed and serverExists set 00071 // to false. 00072 //Arguments: none. 00073 //Returns: 0. 00074 //Called Funcs: none. 00075 //-------------------------------------------------------------------- 00076 Server::~Server() 00077 { 00078 return; 00079 } 00080 00081 //-------------------------------------------------------------------- 00082 //Purpose: retrieve the Document file from its url location. 00083 //Preconditions: Document object, either curl or wget application 00084 // must be available for downloading file.. 00085 //Postconditions: returns true if file retrieval successfull, false if not. 00086 // Only does remote retrieval after checking for local 00087 // presence of the file. The location of the file is set 00088 // for the Document.fileLocation attribute. 00089 //Arguments: Document& doc. 00090 //Returns: bool. 00091 //Called Funcs: Document.getDocumentFile(), ifstream.open(), 00092 // c_str(), system(), Document.getDocumentUrl(), 00093 // Document.setFileLocation(), ifstream.close(). 00094 //-------------------------------------------------------------------- 00095 bool Server::getFile( Document& doc ) 00096 { 00097 string download; // to be set for curl/wget. 00098 00099 // Checking if file already exists in /tmp. 00100 ifstream inputFile; 00101 string tmpDocFile = "/tmp/" + doc.getDocumentFile(); 00102 inputFile.open( tmpDocFile.c_str() ); 00103 if ( !inputFile ) 00104 { 00105 // need to pull the file, so setup either curl or wget. 00106 if ( system( "curl -s http://www.google.com >> /dev/null" ) == 0) 00107 { 00108 download = "curl -O "; 00109 } 00110 else 00111 { 00112 if ( system( "wget -V >> /dev/null " ) == 0 ) 00113 { 00114 download = "wget "; 00115 } 00116 else 00117 { 00118 cout << "Server Error: neither Curl or Wget are operational on this system."; 00119 cout << endl; 00120 exit(1); 00121 } 00122 } 00123 00124 // building system call. 00125 string linuxUrlCall = "cd /tmp; " + download + doc.getDocumentUrl(); 00126 cout << "File is being retrieved..." << endl; 00127 int results = system( linuxUrlCall.c_str() ); 00128 if ( results > 0 ) 00129 { 00130 cout << "Server Error: I am unable to retrieve your URL..."; 00131 cout << endl << "Server Error: Please verify the url before trying again."; 00132 cout << endl; 00133 doc.setFileLocation( "ErrorURL" ); 00134 return false; 00135 } 00136 else 00137 { 00138 // determine document name in url, using basename() function. 00139 string location = "/tmp/" + doc.getDocumentFile(); 00140 doc.setFileLocation( location ); 00141 return true; 00142 } 00143 } 00144 else 00145 { 00146 // file exists in /tmp. 00147 cout << "Server: File has been found locally." << endl; 00148 inputFile.close(); 00149 string location = "/tmp/" + doc.getDocumentFile(); 00150 doc.setFileLocation( location ); 00151 return true; 00152 } 00153 } 00154 00155 //-------------------------------------------------------------------- 00156 //Purpose: conversion of the provided Document, based 00157 // on the objects registered conversion routine. 00158 //Preconditions: Document object. 00159 //Postconditions: returns true if conversion successfull, false if not. 00160 // Converted document location is registered in the 00161 // Document.conLocation attribute. 00162 //Arguments: Document& doc. 00163 //Returns: bool. 00164 //Called Funcs: Document.getDocumentConversion(), 00165 // Document.getFileLocation(), getFile(), 00166 // Document.getDocumentFile(), 00167 // Document.setFileLocation(), 00168 // Document.getDocumentConversion(), system(), 00169 // c_str(), Document.setConversionLocation(). 00170 //-------------------------------------------------------------------- 00171 bool Server::requestConversion( Document& doc ) 00172 { 00173 // check if file has been retrieved before converting. 00174 if ( doc.getFileLocation() == "0" ) 00175 { 00176 // file needs to be retrieved first. 00177 if ( getFile( doc ) ) 00178 { 00179 string location = "/tmp/" + doc.getDocumentFile(); 00180 doc.setFileLocation( location ); 00181 } 00182 } 00183 00184 // attempt to convert file. 00185 string call = "cd /tmp; " + 00186 doc.getDocumentConversion() + 00187 " " + 00188 doc.getFileLocation(); 00189 int results = system( call.c_str() ); 00190 00191 if ( results >= 0 ) 00192 { 00193 // conversion successfull! 00194 doc.setConversionLocation( "/tmp" ); 00195 return true; 00196 } 00197 else 00198 { 00199 // system call has problems. 00200 cout << "Server Error: Conversion failed!!!!!" << endl; 00201 return false; 00202 } 00203 } 00204 00205 00206 //-------------------------------------------------------------------- 00207 //Purpose: obtain list of conversions in database. 00208 //Preconditions: DB must be available. 00209 //Postconditions: returns Result object contianing the list of available 00210 // conversions. 00211 // This is a 5 column answer: 00212 // routine_name, 00213 // from_feature_type, 00214 // to_feature_type, 00215 // from_representation_type, 00216 // to_representation_type. 00217 //Arguments: none. 00218 //Returns: Result. 00219 //Called Funcs: Connection(), Transaction(), Result(), 00220 // Transaction.Exec(), Transaction.Commit(). 00221 //-------------------------------------------------------------------- 00222 Result Server::listConversionDB() 00223 { 00224 try 00225 { 00226 // my query. 00227 string query = "SELECT DISTINCT Filter.routine_name, Filter.from_feature_type, Filter.to_feature_type, "; 00228 query = query + "Filter.from_representation_type, Filter.to_representation_type FROM Filter, Routine "; 00229 query = query + "WHERE Filter.routine_name = Routine.name;"; 00230 00231 // setup connection. 00232 Connection myConnect( "dbname=clearinghouse user=pronir" ); 00233 00234 // Begin a transaction acting on our current connection. 00235 Transaction myTrans(myConnect, "listingConversions"); 00236 00237 // Perform a query on the database, storing result tuples in R 00238 Result myResult = myTrans.Exec( query.c_str() ); 00239 00240 // Tell transation that it was successful. 00241 myTrans.Commit(); 00242 00243 // return the results object. 00244 return myResult; 00245 } 00246 catch ( const exception &e) 00247 { 00248 // All exceptions thrown by libpqxx are derived from std::exception. 00249 cerr << "Exception: " << e.what() << endl; 00250 exit(2); 00251 } 00252 catch (...) 00253 { 00254 // This is really unexpected (see above). 00255 cerr << "Unhandled exception..." << endl; 00256 exit(100); 00257 } 00258 } 00259 00260 00261 //-------------------------------------------------------------------- 00262 //Purpose: obtain list of conversions in database based on 00263 // given representation type. 00264 //Preconditions: DB must be available. 00265 //Postconditions: returns Result object contianing the list of available 00266 // conversions. 00267 // This is a 5 column answer: 00268 // routine_name, 00269 // from_feature_type, 00270 // to_feature_type, 00271 // from_representation_type, 00272 // to_representation_type. 00273 //Arguments: none. 00274 //Returns: Result. 00275 //Called Funcs: Connection(), Transaction(), Result(), 00276 // Transaction.Exec(), Transaction.Commit(). 00277 //-------------------------------------------------------------------- 00278 Result Server::listRepesentationTypes( string representationType ) 00279 { 00280 try 00281 { 00282 // 00283 // my query, careful with the spacing... 00284 // 00285 string query = "SELECT DISTINCT Filter.routine_name, Filter.from_feature_type, Filter.to_feature_type, "; 00286 query = query + "Filter.from_representation_type, Filter.to_representation_type FROM Filter, Routine "; 00287 query = query + "WHERE Filter.from_representation_type='"; 00288 query = query + representationType + "' "; 00289 // query = query + "OR Filter.from_representation_type='*' "; 00290 query = query + "OR Filter.to_representation_type='"; 00291 query = query + representationType + "' "; 00292 query = query + ";"; 00293 // query = query + "OR Filter.to_representation_type='*'; "; 00294 00295 // setup connection. 00296 Connection myConnect( "dbname=clearinghouse user=pronir" ); 00297 00298 // Begin a transaction acting on our current connection. 00299 Transaction myTrans(myConnect, "listingRepresentationTypes"); 00300 00301 // Perform a query on the database, storing result tuples in R 00302 Result myResult = myTrans.Exec( query.c_str() ); 00303 00304 // Tell transation that it was successful. 00305 myTrans.Commit(); 00306 00307 // return the results object. 00308 return myResult; 00309 } 00310 catch ( const exception &e) 00311 { 00312 // All exceptions thrown by libpqxx are derived from std::exception. 00313 cerr << "Exception: " << e.what() << endl; 00314 exit(2); 00315 } 00316 catch (...) 00317 { 00318 // This is really unexpected (see above). 00319 cerr << "Unhandled exception..." << endl; 00320 exit(100); 00321 } 00322 } 00323 00324 00325 //-------------------------------------------------------------------- 00326 //Purpose: obtain list of conversions in database based on 00327 // given feature type. 00328 //Preconditions: DB must be available. 00329 //Postconditions: returns Result object contianing the list of available 00330 // conversions. 00331 // This is a 5 column answer: 00332 // routine_name, 00333 // from_feature_type, 00334 // to_feature_type, 00335 // from_representation_type, 00336 // to_representation_type. 00337 //Arguments: none. 00338 //Returns: Result. 00339 //Called Funcs: Connection(), Transaction(), Result(), 00340 // Transaction.Exec(), Transaction.Commit(). 00341 //-------------------------------------------------------------------- 00342 Result Server::listFeatureTypes( string featureType ) 00343 { 00344 try 00345 { 00346 // 00347 // my query, careful with the spacing... 00348 // 00349 string query = "SELECT DISTINCT Filter.routine_name, Filter.from_feature_type, Filter.to_feature_type, "; 00350 query = query + "Filter.from_representation_type, Filter.to_representation_type FROM Filter, Routine "; 00351 query = query + "WHERE Filter.from_feature_type='"; 00352 query = query + featureType + "' "; 00353 // query = query + "OR Filter.from_feature_type='*' "; 00354 query = query + "OR Filter.to_feature_type='"; 00355 query = query + featureType + "' "; 00356 query = query + ";"; 00357 // query = query + "OR Filter.to_feature_type='*'; "; 00358 00359 // setup connection. 00360 Connection myConnect( "dbname=clearinghouse user=pronir" ); 00361 00362 // Begin a transaction acting on our current connection. 00363 Transaction myTrans(myConnect, "listingFeatureTypes"); 00364 00365 // Perform a query on the database, storing result tuples in R 00366 Result myResult = myTrans.Exec( query.c_str() ); 00367 00368 // Tell transation that it was successful. 00369 myTrans.Commit(); 00370 00371 // return the results object. 00372 return myResult; 00373 } 00374 catch ( const exception &e) 00375 { 00376 // All exceptions thrown by libpqxx are derived from std::exception. 00377 cerr << "Exception: " << e.what() << endl; 00378 exit(2); 00379 } 00380 catch (...) 00381 { 00382 // This is really unexpected (see above). 00383 cerr << "Unhandled exception..." << endl; 00384 exit(100); 00385 } 00386 }