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 "BESRegex.h"
49 #include "BESUtil.h"
50 
51 map<string, BESCatalogUtils *> BESCatalogUtils::_instances ;
52 
53 BESCatalogUtils::
54 BESCatalogUtils( const string &n )
55  : _follow_syms( false )
56 {
57  string key = "BES.Catalog." + n + ".RootDirectory" ;
58  bool found = false ;
59  TheBESKeys::TheKeys()->get_value( key, _root_dir, found ) ;
60  if( !found || _root_dir == "" )
61  {
62  string s = key + " not defined in BES configuration file" ;
63  throw BESSyntaxUserError( s, __FILE__, __LINE__ ) ;
64  }
65  DIR *dip = opendir( _root_dir.c_str() ) ;
66  if( dip == NULL )
67  {
68  string serr = "BESCatalogDirectory - root directory "
69  + _root_dir + " does not exist" ;
70  throw BESNotFoundError( serr, __FILE__, __LINE__ ) ;
71  }
72  closedir( dip ) ;
73 
74  found = false ;
75  key = (string)"BES.Catalog." + n + ".Exclude" ;
76  vector<string> vals ;
77  TheBESKeys::TheKeys()->get_values( key, vals, found ) ;
78  vector<string>::iterator ei = vals.begin() ;
79  vector<string>::iterator ee = vals.end() ;
80  for( ; ei != ee; ei++ )
81  {
82  string e_str = (*ei) ;
83  if( !e_str.empty() && e_str != ";" )
84  BESUtil::explode( ';', e_str, _exclude ) ;
85  }
86 
87  key = (string)"BES.Catalog." + n + ".Include" ;
88  vals.clear() ;
89  TheBESKeys::TheKeys()->get_values( key, vals, found ) ;
90  vector<string>::iterator ii = vals.begin() ;
91  vector<string>::iterator ie = vals.end() ;
92  for( ; ii != ie; ii++ )
93  {
94  string i_str = (*ii) ;
95  if( !i_str.empty() && i_str != ";" )
96  BESUtil::explode( ';', i_str, _include ) ;
97  }
98 
99  key = "BES.Catalog." + n + ".TypeMatch" ;
100  list<string> match_list ;
101  vals.clear() ;
102  TheBESKeys::TheKeys()->get_values( key, vals, found ) ;
103  if( !found || vals.size() == 0 )
104  {
105  string s = key + " not defined in key file" ;
106  throw BESInternalError( s, __FILE__, __LINE__ ) ;
107  }
108  vector<string>::iterator vi = vals.begin() ;
109  vector<string>::iterator ve = vals.end() ;
110  for( ; vi != ve; vi++ )
111  {
112  BESUtil::explode( ';', (*vi), match_list ) ;
113  }
114 
115  list<string>::iterator mli = match_list.begin() ;
116  list<string>::iterator mle = match_list.end() ;
117  for( ; mli != mle; mli++ )
118  {
119  if( !((*mli).empty()) && *(mli) != ";" )
120  {
121  list<string> amatch ;
122  BESUtil::explode( ':', (*mli), amatch ) ;
123  if( amatch.size() != 2 )
124  {
125  string s = (string)"Catalog type match malformed, "
126  + "looking for type:regexp;[type:regexp;]" ;
127  throw BESInternalError( s, __FILE__, __LINE__ ) ;
128  }
129  list<string>::iterator ami = amatch.begin() ;
130  type_reg newval ;
131  newval.type = (*ami) ;
132  ami++ ;
133  newval.reg = (*ami) ;
134  _match_list.push_back( newval ) ;
135  }
136  }
137 
138  key = (string)"BES.Catalog." + n + ".FollowSymLinks" ;
139  string s_str ;
140  TheBESKeys::TheKeys()->get_value( key, s_str, found ) ;
141  s_str = BESUtil::lowercase( s_str ) ;
142  if( s_str == "yes" || s_str == "on" || s_str == "true" )
143  {
144  _follow_syms = true ;
145  }
146 }
147 
148 bool
149 BESCatalogUtils::include( const string &inQuestion ) const
150 {
151  bool toInclude = false ;
152 
153  // First check the file against the include list. If the file should be
154  // included then check the exclude list to see if there are exceptions
155  // to the include list.
156  if( _include.size() == 0 )
157  {
158  toInclude = true ;
159  }
160  else
161  {
162  list<string>::const_iterator i_iter = _include.begin() ;
163  list<string>::const_iterator i_end = _include.end() ;
164  for( ; i_iter != i_end; i_iter++ )
165  {
166  string reg = *i_iter ;
167  if( !reg.empty() )
168  {
169  try
170  {
171  // must match exactly, meaing result is = to length of string
172  // in question
173  BESRegex reg_expr( reg.c_str() ) ;
174  if( reg_expr.match( inQuestion.c_str(),
175  inQuestion.length() ) ==
176  static_cast<int>(inQuestion.length()) )
177  {
178  toInclude = true ;
179  }
180  }
181  catch( BESError &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_message() ;
187  throw BESInternalError( serr, __FILE__, __LINE__ ) ;
188  }
189  }
190  }
191  }
192 
193  if( toInclude == true )
194  {
195  if( exclude( inQuestion ) )
196  {
197  toInclude = false ;
198  }
199  }
200 
201  return toInclude ;
202 }
203 
204 bool
205 BESCatalogUtils::exclude( const string &inQuestion ) const
206 {
207  list<string>::const_iterator e_iter = _exclude.begin() ;
208  list<string>::const_iterator e_end = _exclude.end() ;
209  for( ; e_iter != e_end; e_iter++ )
210  {
211  string reg = *e_iter ;
212  if( !reg.empty() )
213  {
214  try
215  {
216  BESRegex reg_expr( reg.c_str() ) ;
217  if( reg_expr.match( inQuestion.c_str(), inQuestion.length() ) ==
218  static_cast<int>(inQuestion.length()) )
219  {
220  return true ;
221  }
222  }
223  catch( BESError &e )
224  {
225  string serr = (string)"Unable to get catalog information, "
226  + "malformed Catalog Exclude parameter "
227  + "in bes configuration file around "
228  + reg + ": " + e.get_message() ;
229  throw BESInternalError( serr, __FILE__, __LINE__ ) ;
230  }
231  }
232  }
233  return false ;
234 }
235 
238 {
239  return _match_list.begin() ;
240 }
241 
244 {
245  return _match_list.end() ;
246 }
247 
248 void
249 BESCatalogUtils::dump( ostream &strm ) const
250 {
251  strm << BESIndent::LMarg << "BESCatalogUtils::dump - ("
252  << (void *)this << ")" << endl ;
254 
255  strm << BESIndent::LMarg << "root directory: " << _root_dir << endl ;
256 
257  if( _include.size() )
258  {
259  strm << BESIndent::LMarg << "include list:" << endl ;
260  BESIndent::Indent() ;
261  list<string>::const_iterator i_iter = _include.begin() ;
262  list<string>::const_iterator i_end = _include.end() ;
263  for( ; i_iter != i_end; i_iter++ )
264  {
265  if( !(*i_iter).empty() )
266  {
267  strm << BESIndent::LMarg << *i_iter << endl ;
268  }
269  }
271  }
272  else
273  {
274  strm << BESIndent::LMarg << "include list: empty" << endl ;
275  }
276 
277  if( _exclude.size() )
278  {
279  strm << BESIndent::LMarg << "exclude list:" << endl ;
280  BESIndent::Indent() ;
281  list<string>::const_iterator e_iter = _exclude.begin() ;
282  list<string>::const_iterator e_end = _exclude.end() ;
283  for( ; e_iter != e_end; e_iter++ )
284  {
285  if( !(*e_iter).empty() )
286  {
287  strm << BESIndent::LMarg << *e_iter << endl ;
288  }
289  }
291  }
292  else
293  {
294  strm << BESIndent::LMarg << "exclude list: empty" << endl ;
295  }
296 
297  if( _match_list.size() )
298  {
299  strm << BESIndent::LMarg << "type matches:" << endl ;
300  BESIndent::Indent() ;
301  BESCatalogUtils::match_citer i = _match_list.begin() ;
302  BESCatalogUtils::match_citer ie = _match_list.end() ;
303  for( ; i != ie; i++ )
304  {
305  type_reg match = (*i) ;
306  strm << BESIndent::LMarg << match.type << " : "
307  << match.reg << endl ;
308  }
310  }
311  else
312  {
313  strm << BESIndent::LMarg << " type matches: empty" << endl ;
314  }
315 
316  if( _follow_syms )
317  {
318  strm << BESIndent::LMarg << " follow symbolic links: on" << endl ;
319  }
320  else
321  {
322  strm << BESIndent::LMarg << " follow symbolic links: off" << endl ;
323  }
324 
326 }
327 
328 const BESCatalogUtils *
329 BESCatalogUtils::Utils( const string &cat_name )
330 {
331  BESCatalogUtils *utils = BESCatalogUtils::_instances[cat_name] ;
332  if( !utils )
333  {
334  utils = new BESCatalogUtils( cat_name );
335  BESCatalogUtils::_instances[cat_name] = utils ;
336  }
337  return utils ;
338 }
339