BESCatalogUtils.cc

Go to the documentation of this file.
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,2005 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 "sys/types.h"
00034 #include "sys/stat.h"
00035 #include "dirent.h"
00036 
00037 #include "BESCatalogUtils.h"
00038 #include "TheBESKeys.h"
00039 #include "BESInternalError.h"
00040 #include "BESNotFoundError.h"
00041 #include "GNURegex.h"
00042 #include "Error.h"
00043 
00044 using namespace libdap ;
00045 
00046 map<string, BESCatalogUtils *> BESCatalogUtils::_instances ;
00047 
00048 BESCatalogUtils::
00049 BESCatalogUtils( const string &n )
00050     : _follow_syms( false )
00051 {
00052     string key = "BES.Catalog." + n + ".RootDirectory" ;
00053     bool found = false ;
00054     _root_dir = TheBESKeys::TheKeys()->get_key( key, found ) ;
00055     if( !found || _root_dir == "" )
00056     {
00057         string s = key + " not defined in key file" ;
00058         throw BESInternalError( s, __FILE__, __LINE__ ) ;
00059     }
00060     DIR *dip = opendir( _root_dir.c_str() ) ;
00061     if( dip == NULL )
00062     {
00063         string serr = "BESCatalogDirectory - root directory "
00064                       + _root_dir + " does not exist" ;
00065         throw BESNotFoundError( serr, __FILE__, __LINE__ ) ;
00066     }
00067     closedir( dip ) ;
00068 
00069     key = (string)"BES.Catalog." + n + ".Exclude" ;
00070     string e_str = TheBESKeys::TheKeys()->get_key( key, found ) ;
00071     if( found && e_str != "" && e_str != ";" )
00072     {
00073         build_list( _exclude, e_str ) ;
00074     }
00075 
00076     key = (string)"BES.Catalog." + n + ".Include" ;
00077     string i_str = TheBESKeys::TheKeys()->get_key( key, found ) ;
00078     if( found && i_str != "" && i_str != ";" )
00079     {
00080         build_list( _include, i_str ) ;
00081     }
00082 
00083     key = "BES.Catalog." + n + ".TypeMatch" ;
00084     string curr_str = TheBESKeys::TheKeys()->get_key( key, found ) ;
00085     if( curr_str == "" )
00086     {
00087         string s = key + " not defined in key file" ;
00088         throw BESInternalError( s, __FILE__, __LINE__ ) ;
00089     }
00090 
00091     string::size_type str_begin = 0 ;
00092     string::size_type str_end = curr_str.length() ;
00093     string::size_type semi = 0 ;
00094     bool done = false ;
00095     while( done == false )
00096     {
00097         semi = curr_str.find( ";", str_begin ) ;
00098         if( semi == string::npos )
00099         {
00100             string s = (string)"Catalog type match malformed, no semicolon, "
00101                        "looking for type:regexp;[type:regexp;]" ;
00102             throw BESInternalError( s, __FILE__, __LINE__ ) ;
00103         }
00104         else
00105         {
00106             string a_pair = curr_str.substr( str_begin, semi-str_begin ) ;
00107             str_begin = semi+1 ;
00108             if( semi == str_end-1 )
00109             {
00110                 done = true ;
00111             }
00112 
00113             string::size_type col = a_pair.find( ":" ) ;
00114             if( col == string::npos )
00115             {
00116                 string s = (string)"Catalog type match malformed, no colon, "
00117                            + "looking for type:regexp;[type:regexp;]" ;
00118                 throw BESInternalError( s, __FILE__, __LINE__ ) ;
00119             }
00120             else
00121             {
00122                 type_reg newval ;
00123                 newval.type = a_pair.substr( 0, col ) ;
00124                 newval.reg = a_pair.substr( col+1, a_pair.length()-col ) ;
00125                 _match_list.push_back( newval ) ;
00126             }
00127         }
00128     }
00129 
00130     key = (string)"BES.Catalog." + n + ".FollowSymLinks" ;
00131     string s_str =
00132         BESUtil::lowercase( TheBESKeys::TheKeys()->get_key( key, found ) ) ;
00133     if( found && ( s_str == "yes" || s_str == "on" || s_str == "true" ) )
00134     {
00135         _follow_syms = true ;
00136     }
00137 }
00138 
00139 void
00140 BESCatalogUtils::build_list( list<string> &theList, const string &listStr )
00141 {
00142     string::size_type str_begin = 0 ;
00143     string::size_type str_end = listStr.length() ;
00144     string::size_type semi = 0 ;
00145     bool done = false ;
00146     while( done == false )
00147     {
00148         semi = listStr.find( ";", str_begin ) ;
00149         if( semi == string::npos )
00150         {
00151             string s = (string)"Catalog type match malformed, no semicolon, "
00152                        "looking for type:regexp;[type:regexp;]" ;
00153             throw BESInternalError( s, __FILE__, __LINE__ ) ;
00154         }
00155         else
00156         {
00157             string a_member = listStr.substr( str_begin, semi-str_begin ) ;
00158             str_begin = semi+1 ;
00159             if( semi == str_end-1 )
00160             {
00161                 done = true ;
00162             }
00163             if( a_member != "" ) theList.push_back( a_member ) ;
00164         }
00165     }
00166 }
00167 
00168 bool
00169 BESCatalogUtils::include( const string &inQuestion ) const
00170 {
00171     bool toInclude = false ;
00172 
00173     // First check the file against the include list. If the file should be
00174     // included then check the exclude list to see if there are exceptions
00175     // to the include list.
00176     if( _include.size() == 0 )
00177     {
00178         toInclude = true ;
00179     }
00180     else
00181     {
00182         list<string>::const_iterator i_iter = _include.begin() ;
00183         list<string>::const_iterator i_end = _include.end() ;
00184         for( ; i_iter != i_end; i_iter++ )
00185         {
00186             string reg = *i_iter ;
00187             try
00188             {
00189                 // must match exactly, meaing result is = to length of string
00190                 // in question
00191                 Regex reg_expr( reg.c_str() ) ;
00192                 if( reg_expr.match( inQuestion.c_str(), inQuestion.length() ) == inQuestion.length() )
00193                 {
00194                     toInclude = true ;
00195                 }
00196             }
00197             catch( Error &e )
00198             {
00199                 string serr = (string)"Unable to get catalog information, "
00200                               + "malformed Catalog Include parameter "
00201                               + "in bes configuration file around " 
00202                               + reg + ": " + e.get_error_message() ;
00203                 throw BESInternalError( serr, __FILE__, __LINE__ ) ;
00204             }
00205         }
00206     }
00207 
00208     if( toInclude == true )
00209     {
00210         if( exclude( inQuestion ) )
00211         {
00212             toInclude = false ;
00213         }
00214     }
00215 
00216     return toInclude ;
00217 }
00218 
00219 bool
00220 BESCatalogUtils::exclude( const string &inQuestion ) const
00221 {
00222     list<string>::const_iterator e_iter = _exclude.begin() ;
00223     list<string>::const_iterator e_end = _exclude.end() ;
00224     for( ; e_iter != e_end; e_iter++ )
00225     {
00226         string reg = *e_iter ;
00227         try
00228         {
00229             Regex reg_expr( reg.c_str() ) ;
00230             if( reg_expr.match( inQuestion.c_str(), inQuestion.length() ) == inQuestion.length() )
00231             {
00232                 return true ;
00233             }
00234         }
00235         catch( Error &e )
00236         {
00237             string serr = (string)"Unable to get catalog information, "
00238                           + "malformed Catalog Exclude parameter " 
00239                           + "in bes configuration file around " 
00240                           + reg + ": " + e.get_error_message() ;
00241             throw BESInternalError( serr, __FILE__, __LINE__ ) ;
00242         }
00243     }
00244     return false ;
00245 }
00246 
00247 BESCatalogUtils::match_citer
00248 BESCatalogUtils::match_list_begin() const
00249 {
00250     return _match_list.begin() ;
00251 }
00252 
00253 BESCatalogUtils::match_citer
00254 BESCatalogUtils::match_list_end() const
00255 {
00256     return _match_list.end() ;
00257 }
00258 
00259 void
00260 BESCatalogUtils::dump( ostream &strm ) const
00261 {
00262     strm << BESIndent::LMarg << "BESCatalogUtils::dump - ("
00263                              << (void *)this << ")" << endl ;
00264     BESIndent::Indent() ;
00265 
00266     strm << BESIndent::LMarg << "root directory: " << _root_dir << endl ;
00267 
00268     if( _include.size() )
00269     {
00270         strm << BESIndent::LMarg << "include list:" << endl ;
00271         BESIndent::Indent() ;
00272         list<string>::const_iterator i_iter = _include.begin() ;
00273         list<string>::const_iterator i_end = _include.end() ;
00274         for( ; i_iter != i_end; i_iter++ )
00275         {
00276             strm << BESIndent::LMarg << *i_iter << endl ;
00277         }
00278         BESIndent::UnIndent() ;
00279     }
00280     else
00281     {
00282         strm << BESIndent::LMarg << "include list: empty" << endl ;
00283     }
00284 
00285     if( _exclude.size() )
00286     {
00287         strm << BESIndent::LMarg << "exclude list:" << endl ;
00288         BESIndent::Indent() ;
00289         list<string>::const_iterator e_iter = _exclude.begin() ;
00290         list<string>::const_iterator e_end = _exclude.end() ;
00291         for( ; e_iter != e_end; e_iter++ )
00292         {
00293             strm << BESIndent::LMarg << *e_iter << endl ;
00294         }
00295         BESIndent::UnIndent() ;
00296     }
00297     else
00298     {
00299         strm << BESIndent::LMarg << "exclude list: empty" << endl ;
00300     }
00301 
00302     if( _match_list.size() )
00303     {
00304         strm << BESIndent::LMarg << "type matches:" << endl ;
00305         BESIndent::Indent() ;
00306         BESCatalogUtils::match_citer i = _match_list.begin() ;
00307         BESCatalogUtils::match_citer ie = _match_list.end() ;
00308         for( ; i != ie; i++ )
00309         {
00310             type_reg match = (*i) ;
00311             strm << BESIndent::LMarg << match.type << " : "
00312                                      << match.reg << endl ;
00313         }
00314         BESIndent::UnIndent() ;
00315     }
00316     else
00317     {
00318         strm << BESIndent::LMarg << "    type matches: empty" << endl ;
00319     }
00320 
00321     if( _follow_syms )
00322     {
00323         strm << BESIndent::LMarg << "    follow symbolic links: on" << endl ;
00324     }
00325     else
00326     {
00327         strm << BESIndent::LMarg << "    follow symbolic links: off" << endl ;
00328     }
00329 
00330     BESIndent::UnIndent() ;
00331 }
00332 
00333 const BESCatalogUtils *
00334 BESCatalogUtils::Utils( const string &cat_name )
00335 {
00336     BESCatalogUtils *utils = BESCatalogUtils::_instances[cat_name] ;
00337     if( !utils )
00338     {
00339         utils = new BESCatalogUtils( cat_name );
00340         BESCatalogUtils::_instances[cat_name] = utils ;
00341     }
00342     return utils ;
00343 }
00344 

Generated on Tue Mar 4 23:13:33 2008 for OPeNDAP Back End Server (BES) by  doxygen 1.5.1