OPeNDAP Hyrax Back End Server (BES) Updated for version 3.8.3
|
00001 // BESCatalogUtils.cc 00002 00003 // This file is part of bes, A C++ back-end server implementation framework 00004 // for the OPeNDAP Data Access Protocol. 00005 00006 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research 00007 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu> 00008 // 00009 // This library is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU Lesser General Public 00011 // License as published by the Free Software Foundation; either 00012 // version 2.1 of the License, or (at your option) any later version. 00013 // 00014 // This library is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 // Lesser General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU Lesser General Public 00020 // License along with this library; if not, write to the Free Software 00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 // 00023 // You can contact University Corporation for Atmospheric Research at 00024 // 3080 Center Green Drive, Boulder, CO 80301 00025 00026 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005 00027 // Please read the full copyright statement in the file COPYRIGHT_UCAR. 00028 // 00029 // Authors: 00030 // pwest Patrick West <pwest@ucar.edu> 00031 // jgarcia Jose Garcia <jgarcia@ucar.edu> 00032 00033 #include "config.h" 00034 00035 #include <sys/types.h> 00036 #include <sys/stat.h> 00037 #include <dirent.h> 00038 00039 #include <iostream> 00040 using std::cout ; 00041 using std::endl ; 00042 00043 #include "BESCatalogUtils.h" 00044 #include "TheBESKeys.h" 00045 #include "BESInternalError.h" 00046 #include "BESSyntaxUserError.h" 00047 #include "BESNotFoundError.h" 00048 #include "GNURegex.h" 00049 #include "Error.h" 00050 #include "BESUtil.h" 00051 00052 using namespace libdap ; 00053 00054 map<string, BESCatalogUtils *> BESCatalogUtils::_instances ; 00055 00056 BESCatalogUtils:: 00057 BESCatalogUtils( const string &n ) 00058 : _follow_syms( false ) 00059 { 00060 string key = "BES.Catalog." + n + ".RootDirectory" ; 00061 bool found = false ; 00062 TheBESKeys::TheKeys()->get_value( key, _root_dir, found ) ; 00063 if( !found || _root_dir == "" ) 00064 { 00065 string s = key + " not defined in BES configuration file" ; 00066 throw BESSyntaxUserError( s, __FILE__, __LINE__ ) ; 00067 } 00068 DIR *dip = opendir( _root_dir.c_str() ) ; 00069 if( dip == NULL ) 00070 { 00071 string serr = "BESCatalogDirectory - root directory " 00072 + _root_dir + " does not exist" ; 00073 throw BESNotFoundError( serr, __FILE__, __LINE__ ) ; 00074 } 00075 closedir( dip ) ; 00076 00077 found = false ; 00078 key = (string)"BES.Catalog." + n + ".Exclude" ; 00079 vector<string> vals ; 00080 TheBESKeys::TheKeys()->get_values( key, vals, found ) ; 00081 vector<string>::iterator ei = vals.begin() ; 00082 vector<string>::iterator ee = vals.end() ; 00083 for( ; ei != ee; ei++ ) 00084 { 00085 string e_str = (*ei) ; 00086 if( !e_str.empty() && e_str != ";" ) 00087 BESUtil::explode( ';', e_str, _exclude ) ; 00088 } 00089 00090 key = (string)"BES.Catalog." + n + ".Include" ; 00091 vals.clear() ; 00092 TheBESKeys::TheKeys()->get_values( key, vals, found ) ; 00093 vector<string>::iterator ii = vals.begin() ; 00094 vector<string>::iterator ie = vals.end() ; 00095 for( ; ii != ie; ii++ ) 00096 { 00097 string i_str = (*ii) ; 00098 if( !i_str.empty() && i_str != ";" ) 00099 BESUtil::explode( ';', i_str, _include ) ; 00100 } 00101 00102 key = "BES.Catalog." + n + ".TypeMatch" ; 00103 list<string> match_list ; 00104 vals.clear() ; 00105 TheBESKeys::TheKeys()->get_values( key, vals, found ) ; 00106 if( !found || vals.size() == 0 ) 00107 { 00108 string s = key + " not defined in key file" ; 00109 throw BESInternalError( s, __FILE__, __LINE__ ) ; 00110 } 00111 vector<string>::iterator vi = vals.begin() ; 00112 vector<string>::iterator ve = vals.end() ; 00113 for( ; vi != ve; vi++ ) 00114 { 00115 BESUtil::explode( ';', (*vi), match_list ) ; 00116 } 00117 00118 list<string>::iterator mli = match_list.begin() ; 00119 list<string>::iterator mle = match_list.end() ; 00120 for( ; mli != mle; mli++ ) 00121 { 00122 if( !((*mli).empty()) && *(mli) != ";" ) 00123 { 00124 list<string> amatch ; 00125 BESUtil::explode( ':', (*mli), amatch ) ; 00126 if( amatch.size() != 2 ) 00127 { 00128 string s = (string)"Catalog type match malformed, " 00129 + "looking for type:regexp;[type:regexp;]" ; 00130 throw BESInternalError( s, __FILE__, __LINE__ ) ; 00131 } 00132 list<string>::iterator ami = amatch.begin() ; 00133 type_reg newval ; 00134 newval.type = (*ami) ; 00135 ami++ ; 00136 newval.reg = (*ami) ; 00137 _match_list.push_back( newval ) ; 00138 } 00139 } 00140 00141 key = (string)"BES.Catalog." + n + ".FollowSymLinks" ; 00142 string s_str ; 00143 TheBESKeys::TheKeys()->get_value( key, s_str, found ) ; 00144 s_str = BESUtil::lowercase( s_str ) ; 00145 if( s_str == "yes" || s_str == "on" || s_str == "true" ) 00146 { 00147 _follow_syms = true ; 00148 } 00149 } 00150 00151 bool 00152 BESCatalogUtils::include( const string &inQuestion ) const 00153 { 00154 bool toInclude = false ; 00155 00156 // First check the file against the include list. If the file should be 00157 // included then check the exclude list to see if there are exceptions 00158 // to the include list. 00159 if( _include.size() == 0 ) 00160 { 00161 toInclude = true ; 00162 } 00163 else 00164 { 00165 list<string>::const_iterator i_iter = _include.begin() ; 00166 list<string>::const_iterator i_end = _include.end() ; 00167 for( ; i_iter != i_end; i_iter++ ) 00168 { 00169 string reg = *i_iter ; 00170 try 00171 { 00172 // must match exactly, meaing result is = to length of string 00173 // in question 00174 Regex reg_expr( reg.c_str() ) ; 00175 if( reg_expr.match( inQuestion.c_str(), inQuestion.length() ) == 00176 static_cast<int>(inQuestion.length()) ) 00177 { 00178 toInclude = true ; 00179 } 00180 } 00181 catch( Error &e ) 00182 { 00183 string serr = (string)"Unable to get catalog information, " 00184 + "malformed Catalog Include parameter " 00185 + "in bes configuration file around " 00186 + reg + ": " + e.get_error_message() ; 00187 throw BESInternalError( serr, __FILE__, __LINE__ ) ; 00188 } 00189 } 00190 } 00191 00192 if( toInclude == true ) 00193 { 00194 if( exclude( inQuestion ) ) 00195 { 00196 toInclude = false ; 00197 } 00198 } 00199 00200 return toInclude ; 00201 } 00202 00203 bool 00204 BESCatalogUtils::exclude( const string &inQuestion ) const 00205 { 00206 list<string>::const_iterator e_iter = _exclude.begin() ; 00207 list<string>::const_iterator e_end = _exclude.end() ; 00208 for( ; e_iter != e_end; e_iter++ ) 00209 { 00210 string reg = *e_iter ; 00211 try 00212 { 00213 Regex reg_expr( reg.c_str() ) ; 00214 if( reg_expr.match( inQuestion.c_str(), inQuestion.length() ) == 00215 static_cast<int>(inQuestion.length()) ) 00216 { 00217 return true ; 00218 } 00219 } 00220 catch( Error &e ) 00221 { 00222 string serr = (string)"Unable to get catalog information, " 00223 + "malformed Catalog Exclude parameter " 00224 + "in bes configuration file around " 00225 + reg + ": " + e.get_error_message() ; 00226 throw BESInternalError( serr, __FILE__, __LINE__ ) ; 00227 } 00228 } 00229 return false ; 00230 } 00231 00232 BESCatalogUtils::match_citer 00233 BESCatalogUtils::match_list_begin() const 00234 { 00235 return _match_list.begin() ; 00236 } 00237 00238 BESCatalogUtils::match_citer 00239 BESCatalogUtils::match_list_end() const 00240 { 00241 return _match_list.end() ; 00242 } 00243 00244 void 00245 BESCatalogUtils::dump( ostream &strm ) const 00246 { 00247 strm << BESIndent::LMarg << "BESCatalogUtils::dump - (" 00248 << (void *)this << ")" << endl ; 00249 BESIndent::Indent() ; 00250 00251 strm << BESIndent::LMarg << "root directory: " << _root_dir << endl ; 00252 00253 if( _include.size() ) 00254 { 00255 strm << BESIndent::LMarg << "include list:" << endl ; 00256 BESIndent::Indent() ; 00257 list<string>::const_iterator i_iter = _include.begin() ; 00258 list<string>::const_iterator i_end = _include.end() ; 00259 for( ; i_iter != i_end; i_iter++ ) 00260 { 00261 strm << BESIndent::LMarg << *i_iter << endl ; 00262 } 00263 BESIndent::UnIndent() ; 00264 } 00265 else 00266 { 00267 strm << BESIndent::LMarg << "include list: empty" << endl ; 00268 } 00269 00270 if( _exclude.size() ) 00271 { 00272 strm << BESIndent::LMarg << "exclude list:" << endl ; 00273 BESIndent::Indent() ; 00274 list<string>::const_iterator e_iter = _exclude.begin() ; 00275 list<string>::const_iterator e_end = _exclude.end() ; 00276 for( ; e_iter != e_end; e_iter++ ) 00277 { 00278 strm << BESIndent::LMarg << *e_iter << endl ; 00279 } 00280 BESIndent::UnIndent() ; 00281 } 00282 else 00283 { 00284 strm << BESIndent::LMarg << "exclude list: empty" << endl ; 00285 } 00286 00287 if( _match_list.size() ) 00288 { 00289 strm << BESIndent::LMarg << "type matches:" << endl ; 00290 BESIndent::Indent() ; 00291 BESCatalogUtils::match_citer i = _match_list.begin() ; 00292 BESCatalogUtils::match_citer ie = _match_list.end() ; 00293 for( ; i != ie; i++ ) 00294 { 00295 type_reg match = (*i) ; 00296 strm << BESIndent::LMarg << match.type << " : " 00297 << match.reg << endl ; 00298 } 00299 BESIndent::UnIndent() ; 00300 } 00301 else 00302 { 00303 strm << BESIndent::LMarg << " type matches: empty" << endl ; 00304 } 00305 00306 if( _follow_syms ) 00307 { 00308 strm << BESIndent::LMarg << " follow symbolic links: on" << endl ; 00309 } 00310 else 00311 { 00312 strm << BESIndent::LMarg << " follow symbolic links: off" << endl ; 00313 } 00314 00315 BESIndent::UnIndent() ; 00316 } 00317 00318 const BESCatalogUtils * 00319 BESCatalogUtils::Utils( const string &cat_name ) 00320 { 00321 BESCatalogUtils *utils = BESCatalogUtils::_instances[cat_name] ; 00322 if( !utils ) 00323 { 00324 utils = new BESCatalogUtils( cat_name ); 00325 BESCatalogUtils::_instances[cat_name] = utils ; 00326 } 00327 return utils ; 00328 } 00329