OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
BESCatalogUtils.cc
Go to the documentation of this file.
1 // BESCatalogUtils.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <dirent.h>
38 
39 #include <iostream>
40 using std::cout ;
41 using std::endl ;
42 
43 #include "BESCatalogUtils.h"
44 #include "TheBESKeys.h"
45 #include "BESInternalError.h"
46 #include "BESSyntaxUserError.h"
47 #include "BESNotFoundError.h"
48 #include "GNURegex.h"
49 #include "Error.h"
50 #include "BESUtil.h"
51 
52 using namespace libdap ;
53 
54 map<string, BESCatalogUtils *> BESCatalogUtils::_instances ;
55 
56 BESCatalogUtils::
57 BESCatalogUtils( const string &n )
58  : _follow_syms( false )
59 {
60  string key = "BES.Catalog." + n + ".RootDirectory" ;
61  bool found = false ;
62  TheBESKeys::TheKeys()->get_value( key, _root_dir, found ) ;
63  if( !found || _root_dir == "" )
64  {
65  string s = key + " not defined in BES configuration file" ;
66  throw BESSyntaxUserError( s, __FILE__, __LINE__ ) ;
67  }
68  DIR *dip = opendir( _root_dir.c_str() ) ;
69  if( dip == NULL )
70  {
71  string serr = "BESCatalogDirectory - root directory "
72  + _root_dir + " does not exist" ;
73  throw BESNotFoundError( serr, __FILE__, __LINE__ ) ;
74  }
75  closedir( dip ) ;
76 
77  found = false ;
78  key = (string)"BES.Catalog." + n + ".Exclude" ;
79  vector<string> vals ;
80  TheBESKeys::TheKeys()->get_values( key, vals, found ) ;
81  vector<string>::iterator ei = vals.begin() ;
82  vector<string>::iterator ee = vals.end() ;
83  for( ; ei != ee; ei++ )
84  {
85  string e_str = (*ei) ;
86  if( !e_str.empty() && e_str != ";" )
87  BESUtil::explode( ';', e_str, _exclude ) ;
88  }
89 
90  key = (string)"BES.Catalog." + n + ".Include" ;
91  vals.clear() ;
92  TheBESKeys::TheKeys()->get_values( key, vals, found ) ;
93  vector<string>::iterator ii = vals.begin() ;
94  vector<string>::iterator ie = vals.end() ;
95  for( ; ii != ie; ii++ )
96  {
97  string i_str = (*ii) ;
98  if( !i_str.empty() && i_str != ";" )
99  BESUtil::explode( ';', i_str, _include ) ;
100  }
101 
102  key = "BES.Catalog." + n + ".TypeMatch" ;
103  list<string> match_list ;
104  vals.clear() ;
105  TheBESKeys::TheKeys()->get_values( key, vals, found ) ;
106  if( !found || vals.size() == 0 )
107  {
108  string s = key + " not defined in key file" ;
109  throw BESInternalError( s, __FILE__, __LINE__ ) ;
110  }
111  vector<string>::iterator vi = vals.begin() ;
112  vector<string>::iterator ve = vals.end() ;
113  for( ; vi != ve; vi++ )
114  {
115  BESUtil::explode( ';', (*vi), match_list ) ;
116  }
117 
118  list<string>::iterator mli = match_list.begin() ;
119  list<string>::iterator mle = match_list.end() ;
120  for( ; mli != mle; mli++ )
121  {
122  if( !((*mli).empty()) && *(mli) != ";" )
123  {
124  list<string> amatch ;
125  BESUtil::explode( ':', (*mli), amatch ) ;
126  if( amatch.size() != 2 )
127  {
128  string s = (string)"Catalog type match malformed, "
129  + "looking for type:regexp;[type:regexp;]" ;
130  throw BESInternalError( s, __FILE__, __LINE__ ) ;
131  }
132  list<string>::iterator ami = amatch.begin() ;
133  type_reg newval ;
134  newval.type = (*ami) ;
135  ami++ ;
136  newval.reg = (*ami) ;
137  _match_list.push_back( newval ) ;
138  }
139  }
140 
141  key = (string)"BES.Catalog." + n + ".FollowSymLinks" ;
142  string s_str ;
143  TheBESKeys::TheKeys()->get_value( key, s_str, found ) ;
144  s_str = BESUtil::lowercase( s_str ) ;
145  if( s_str == "yes" || s_str == "on" || s_str == "true" )
146  {
147  _follow_syms = true ;
148  }
149 }
150 
151 bool
152 BESCatalogUtils::include( const string &inQuestion ) const
153 {
154  bool toInclude = false ;
155 
156  // First check the file against the include list. If the file should be
157  // included then check the exclude list to see if there are exceptions
158  // to the include list.
159  if( _include.size() == 0 )
160  {
161  toInclude = true ;
162  }
163  else
164  {
165  list<string>::const_iterator i_iter = _include.begin() ;
166  list<string>::const_iterator i_end = _include.end() ;
167  for( ; i_iter != i_end; i_iter++ )
168  {
169  string reg = *i_iter ;
170  try
171  {
172  // must match exactly, meaing result is = to length of string
173  // in question
174  Regex reg_expr( reg.c_str() ) ;
175  if( reg_expr.match( inQuestion.c_str(), inQuestion.length() ) ==
176  static_cast<int>(inQuestion.length()) )
177  {
178  toInclude = true ;
179  }
180  }
181  catch( Error &e )
182  {
183  string serr = (string)"Unable to get catalog information, "
184  + "malformed Catalog Include parameter "
185  + "in bes configuration file around "
186  + reg + ": " + e.get_error_message() ;
187  throw BESInternalError( serr, __FILE__, __LINE__ ) ;
188  }
189  }
190  }
191 
192  if( toInclude == true )
193  {
194  if( exclude( inQuestion ) )
195  {
196  toInclude = false ;
197  }
198  }
199 
200  return toInclude ;
201 }
202 
203 bool
204 BESCatalogUtils::exclude( const string &inQuestion ) const
205 {
206  list<string>::const_iterator e_iter = _exclude.begin() ;
207  list<string>::const_iterator e_end = _exclude.end() ;
208  for( ; e_iter != e_end; e_iter++ )
209  {
210  string reg = *e_iter ;
211  try
212  {
213  Regex reg_expr( reg.c_str() ) ;
214  if( reg_expr.match( inQuestion.c_str(), inQuestion.length() ) ==
215  static_cast<int>(inQuestion.length()) )
216  {
217  return true ;
218  }
219  }
220  catch( Error &e )
221  {
222  string serr = (string)"Unable to get catalog information, "
223  + "malformed Catalog Exclude parameter "
224  + "in bes configuration file around "
225  + reg + ": " + e.get_error_message() ;
226  throw BESInternalError( serr, __FILE__, __LINE__ ) ;
227  }
228  }
229  return false ;
230 }
231 
234 {
235  return _match_list.begin() ;
236 }
237 
240 {
241  return _match_list.end() ;
242 }
243 
244 void
245 BESCatalogUtils::dump( ostream &strm ) const
246 {
247  strm << BESIndent::LMarg << "BESCatalogUtils::dump - ("
248  << (void *)this << ")" << endl ;
250 
251  strm << BESIndent::LMarg << "root directory: " << _root_dir << endl ;
252 
253  if( _include.size() )
254  {
255  strm << BESIndent::LMarg << "include list:" << endl ;
257  list<string>::const_iterator i_iter = _include.begin() ;
258  list<string>::const_iterator i_end = _include.end() ;
259  for( ; i_iter != i_end; i_iter++ )
260  {
261  strm << BESIndent::LMarg << *i_iter << endl ;
262  }
264  }
265  else
266  {
267  strm << BESIndent::LMarg << "include list: empty" << endl ;
268  }
269 
270  if( _exclude.size() )
271  {
272  strm << BESIndent::LMarg << "exclude list:" << endl ;
274  list<string>::const_iterator e_iter = _exclude.begin() ;
275  list<string>::const_iterator e_end = _exclude.end() ;
276  for( ; e_iter != e_end; e_iter++ )
277  {
278  strm << BESIndent::LMarg << *e_iter << endl ;
279  }
281  }
282  else
283  {
284  strm << BESIndent::LMarg << "exclude list: empty" << endl ;
285  }
286 
287  if( _match_list.size() )
288  {
289  strm << BESIndent::LMarg << "type matches:" << endl ;
291  BESCatalogUtils::match_citer i = _match_list.begin() ;
292  BESCatalogUtils::match_citer ie = _match_list.end() ;
293  for( ; i != ie; i++ )
294  {
295  type_reg match = (*i) ;
296  strm << BESIndent::LMarg << match.type << " : "
297  << match.reg << endl ;
298  }
300  }
301  else
302  {
303  strm << BESIndent::LMarg << " type matches: empty" << endl ;
304  }
305 
306  if( _follow_syms )
307  {
308  strm << BESIndent::LMarg << " follow symbolic links: on" << endl ;
309  }
310  else
311  {
312  strm << BESIndent::LMarg << " follow symbolic links: off" << endl ;
313  }
314 
316 }
317 
318 const BESCatalogUtils *
319 BESCatalogUtils::Utils( const string &cat_name )
320 {
321  BESCatalogUtils *utils = BESCatalogUtils::_instances[cat_name] ;
322  if( !utils )
323  {
324  utils = new BESCatalogUtils( cat_name );
325  BESCatalogUtils::_instances[cat_name] = utils ;
326  }
327  return utils ;
328 }
329 
error thrown if the resource requested cannot be found
static const BESCatalogUtils * Utils(const string &name)
exception thrown if inernal error encountered
static string lowercase(const string &s)
Convert a string to all lower case.
Definition: BESUtil.cc:190
BESCatalogUtils::match_citer match_list_end() const
static void Indent()
Definition: BESIndent.cc:38
error thrown if there is a user syntax error in the request or any other user error ...
vector< type_reg >::const_iterator match_citer
virtual void dump(ostream &strm) const
dump the contents of this object to the specified ostream
static ostream & LMarg(ostream &strm)
Definition: BESIndent.cc:73
static void explode(char delim, const string &str, list< string > &values)
explode a string into an array given a delimiter
Definition: BESUtil.cc:513
virtual bool include(const string &inQuestion) const
void get_value(const string &s, string &val, bool &found)
Retrieve the value of a given key, if set.
Definition: BESKeys.cc:466
virtual bool exclude(const string &inQuestion) const
void get_values(const string &s, vector< string > &vals, bool &found)
Retrieve the values of a given key, if set.
Definition: BESKeys.cc:503
BESCatalogUtils::match_citer match_list_begin() const
static void UnIndent()
Definition: BESIndent.cc:44
static BESKeys * TheKeys()
Definition: TheBESKeys.cc:46