bes  Updated for version 3.20.6
TheBESKeys.cc
1 // TheBESKeys.cc
2 
3 // This file is part of bes, A C++ back-end server implementation framework
4 // for the OPeNDAP Data Access Protocol.
5 
6 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research
7 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact University Corporation for Atmospheric Research at
24 // 3080 Center Green Drive, Boulder, CO 80301
25 
26 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
27 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
28 //
29 // Authors:
30 // pwest Patrick West <pwest@ucar.edu>
31 // jgarcia Jose Garcia <jgarcia@ucar.edu>
32 
33 #include "config.h"
34 
35 #if HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
38 
39 #include <cerrno>
40 #include <cstring>
41 
42 #include <string>
43 #include <sstream>
44 
45 #include "TheBESKeys.h"
46 #include "kvp_utils.h"
47 #include "BESUtil.h"
48 #include "BESFSDir.h"
49 #include "BESFSFile.h"
50 #include "BESInternalFatalError.h"
51 #include "BESSyntaxUserError.h"
52 
53 #define BES_INCLUDE_KEY "BES.Include"
54 
55 using namespace std;
56 
57 set<string> TheBESKeys::KeyList;
58 
59 TheBESKeys *TheBESKeys::_instance = 0;
60 string TheBESKeys::ConfigFile = "";
61 
63 {
64  if (_instance) return _instance;
65 
66  if (!TheBESKeys::ConfigFile.empty()) {
67  _instance = new TheBESKeys(TheBESKeys::ConfigFile);
68  return _instance;
69  }
70 
71  // _instance is a nullptr and TheBESKeys::ConfigFile is ""
72  // so lets try some obvious places...
73 
74  string try_ini = "/usr/local/etc/bes/bes.conf";
75  if (access(try_ini.c_str(), R_OK) == 0) {
76  TheBESKeys::ConfigFile = try_ini;
77  _instance = new TheBESKeys(TheBESKeys::ConfigFile);
78  return _instance;
79  }
80 
81  try_ini = "/etc/bes/bes.conf";
82  if (access(try_ini.c_str(), R_OK) == 0) {
83  TheBESKeys::ConfigFile = try_ini;
84  _instance = new TheBESKeys(TheBESKeys::ConfigFile);
85  return _instance;
86  }
87 
88  try_ini = "/usr/etc/bes/bes.conf";
89  if (access(try_ini.c_str(), R_OK) == 0) {
90  TheBESKeys::ConfigFile = try_ini;
91  _instance = new TheBESKeys(TheBESKeys::ConfigFile);
92  return _instance;
93  }
94  throw BESInternalFatalError("Unable to locate a BES configuration file.", __FILE__, __LINE__);
95 }
96 
113 TheBESKeys::TheBESKeys(const string &keys_file_name) :
114  _keys_file(0), _keys_file_name(keys_file_name), _the_keys(0), _own_keys(true)
115 {
116  _the_keys = new map<string, vector<string> >;
117  initialize_keys();
118 }
119 
120 TheBESKeys::TheBESKeys(const string &keys_file_name, map<string, vector<string> > *keys) :
121  _keys_file(0), _keys_file_name(keys_file_name), _the_keys(keys), _own_keys(false)
122 {
123  initialize_keys();
124 }
125 
129 {
130  clean();
131 }
132 
133 void TheBESKeys::initialize_keys()
134 {
135  kvp::load_keys(KeyList, _keys_file_name, *_the_keys);
136 
137 #if 0
138  _keys_file = new ifstream(_keys_file_name.c_str());
139 
140  if (!(*_keys_file)) {
141  char path[500];
142  getcwd(path, sizeof(path));
143  string s = string("Cannot open BES configuration file '") + _keys_file_name + "': ";
144  char *err = strerror(errno);
145  if (err)
146  s += err;
147  else
148  s += "Unknown error";
149 
150  s += (string) ".\n" + "The current working directory is " + path;
151  throw BESInternalFatalError(s, __FILE__, __LINE__);
152  }
153 
154  try {
155  load_keys();
156  }
157  catch (BESError &e) {
158  // be sure we're throwing a fatal error, since the BES can't run
159  // without the configuration file
160  clean();
161  throw BESInternalFatalError(e.get_message(), e.get_file(), e.get_line());
162  }
163  catch (...) {
164  clean();
165  string s = (string) "Undefined exception while trying to load keys from the BES configuration file '"
166  + _keys_file_name + "'";
167  throw BESInternalFatalError(s, __FILE__, __LINE__);
168  }
169 #endif
170 
171 }
172 
173 void TheBESKeys::clean()
174 {
175  if (_keys_file) {
176  _keys_file->close();
177  delete _keys_file;
178  }
179 
180  if (_the_keys && _own_keys) {
181  delete _the_keys;
182  }
183 }
184 
192 bool TheBESKeys::LoadedKeys(const string &key_file)
193 {
194 #if 0
195  vector<string>::const_iterator i = TheBESKeys::KeyList.begin();
196  vector<string>::const_iterator e = TheBESKeys::KeyList.end();
197  for (; i != e; i++) {
198  if ((*i) == key_file) {
199  return true;
200  }
201  }
202 #endif
203  set<string>::iterator it = KeyList.find(key_file);
204 
205  return it!=KeyList.end();
206 }
207 
224 void TheBESKeys::set_key(const string &key, const string &val, bool addto)
225 {
226  map<string, vector<string> >::iterator i;
227  i = _the_keys->find(key);
228  if (i == _the_keys->end()) {
229  vector<string> vals;
230  (*_the_keys)[key] = vals;
231  }
232  if (!addto) (*_the_keys)[key].clear();
233  if (!val.empty()) {
234  (*_the_keys)[key].push_back(val);
235  }
236 }
237 
249 void TheBESKeys::set_key(const string &pair)
250 {
251  string key;
252  string val;
253  bool addto = false;
254  kvp::break_pair(pair.c_str(), key, val, addto);
255  set_key(key, val, addto);
256 }
257 
272 void TheBESKeys::get_value(const string &s, string &val, bool &found)
273 {
274  found = false;
275  map<string, vector<string> >::iterator i;
276  i = _the_keys->find(s);
277  if (i != _the_keys->end()) {
278  found = true;
279  if ((*i).second.size() > 1) {
280  string err = string("Multiple values for the key ") + s + " found, should only be one.";
281  throw BESSyntaxUserError(err, __FILE__, __LINE__);
282  }
283  if ((*i).second.size() == 1) {
284  val = (*i).second[0];
285  }
286  else {
287  val = "";
288  }
289  }
290 }
291 
303 void TheBESKeys::get_values(const string& s, vector<string> &vals, bool &found)
304 {
305  found = false;
306  map<string, vector<string> >::iterator i;
307  i = _the_keys->find(s);
308  if (i != _the_keys->end()) {
309  found = true;
310  vals = (*i).second;
311  }
312 }
313 
326 bool TheBESKeys::read_bool_key(const string &key, bool default_value)
327 {
328  bool found = false;
329  string value;
330  TheBESKeys::TheKeys()->get_value(key, value, found);
331  // 'key' holds the string value at this point if key_found is true
332  if (found) {
333  value = BESUtil::lowercase(value);
334  return (value == "true" || value == "yes"|| value == "on");
335  }
336  else {
337  return default_value;
338  }
339  }
340 
351 string TheBESKeys::read_string_key(const string &key, const string &default_value)
352 {
353  bool found = false;
354  string value;
355  TheBESKeys::TheKeys()->get_value(key, value, found);
356  // 'value' holds the string value at this point if found is true
357  if (found) {
358  if (value[value.length() - 1] == '/') value.erase(value.length() - 1);
359  return value;
360  }
361  else {
362  return default_value;
363  }
364 }
365 
376 int TheBESKeys::read_int_key(const string &key, int default_value)
377 {
378  bool found = false;
379  string value;
380  TheBESKeys::TheKeys()->get_value(key, value, found);
381  // 'key' holds the string value at this point if found is true
382  if (found) {
383  std::istringstream iss(value);
384  int int_val;
385  iss >> int_val;
386  if (iss.eof() || iss.bad() || iss.fail())
387  return default_value;
388  else
389  return int_val;
390  }
391  else {
392  return default_value;
393  }
394 }
395 
402 void TheBESKeys::dump(ostream &strm) const
403 {
404  strm << BESIndent::LMarg << "BESKeys::dump - (" << (void *) this << ")" << endl;
405  BESIndent::Indent();
406  strm << BESIndent::LMarg << "key file:" << _keys_file_name << endl;
407  if (_keys_file && *_keys_file) {
408  strm << BESIndent::LMarg << "key file is valid" << endl;
409  }
410  else {
411  strm << BESIndent::LMarg << "key file is NOT valid" << endl;
412  }
413  if (_the_keys && _the_keys->size()) {
414  strm << BESIndent::LMarg << " keys:" << endl;
415  BESIndent::Indent();
416  Keys_citer i = _the_keys->begin();
417  Keys_citer ie = _the_keys->end();
418  for (; i != ie; i++) {
419  strm << BESIndent::LMarg << (*i).first << ": " /*<< endl*/;
420  // BESIndent::Indent();
421  vector<string>::const_iterator v = (*i).second.begin();
422  vector<string>::const_iterator ve = (*i).second.end();
423  for (; v != ve; v++) {
424  strm << (*v) << " "; //endl;
425  }
426  strm << endl;
427  //BESIndent::UnIndent();
428  }
429  BESIndent::UnIndent();
430  }
431  else {
432  strm << BESIndent::LMarg << "keys: none" << endl;
433  }
434  BESIndent::UnIndent();
435 }
436 
BESError::get_line
virtual int get_line()
get the line number where the exception was thrown
Definition: BESError.h:115
TheBESKeys::ConfigFile
static std::string ConfigFile
Definition: TheBESKeys.h:149
BESInternalFatalError
exception thrown if an internal error is found and is fatal to the BES
Definition: BESInternalFatalError.h:43
BESError::get_message
virtual std::string get_message()
get the error message for this exception
Definition: BESError.h:99
TheBESKeys::read_string_key
std::string read_string_key(const std::string &key, const std::string &default_value)
Read a string-valued key from the bes.conf file.
Definition: TheBESKeys.cc:351
BESError::get_file
virtual std::string get_file()
get the file name where the exception was thrown
Definition: BESError.h:107
TheBESKeys::read_bool_key
bool read_bool_key(const std::string &key, bool default_value)
Read a boolean-valued key from the bes.conf file.
Definition: TheBESKeys.cc:326
TheBESKeys::TheKeys
static TheBESKeys * TheKeys()
Definition: TheBESKeys.cc:62
TheBESKeys
mapping of key/value pairs defining different behaviors of an application.
Definition: TheBESKeys.h:80
BESSyntaxUserError
error thrown if there is a user syntax error in the request or any other user error
Definition: BESSyntaxUserError.h:41
TheBESKeys::get_value
void get_value(const std::string &s, std::string &val, bool &found)
Retrieve the value of a given key, if set.
Definition: TheBESKeys.cc:272
TheBESKeys::get_values
void get_values(const std::string &s, std::vector< std::string > &vals, bool &found)
Retrieve the values of a given key, if set.
Definition: TheBESKeys.cc:303
BESUtil::lowercase
static std::string lowercase(const std::string &s)
Definition: BESUtil.cc:200
TheBESKeys::set_key
void set_key(const std::string &key, const std::string &val, bool addto=false)
allows the user to set key/value pairs from within the application.
Definition: TheBESKeys.cc:224
BESError
Abstract exception class for the BES with basic string message.
Definition: BESError.h:58
TheBESKeys::~TheBESKeys
virtual ~TheBESKeys()
cleans up the key/value pair mapping
Definition: TheBESKeys.cc:128
TheBESKeys::dump
virtual void dump(std::ostream &strm) const
dumps information about this object
Definition: TheBESKeys.cc:402
TheBESKeys::read_int_key
int read_int_key(const std::string &key, int default_value)
Read an integer-valued key from the bes.conf file.
Definition: TheBESKeys.cc:376