BESCatalogDirectory.cc

Go to the documentation of this file.
00001 // BESCatalogDirectory.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 #include "stdio.h"
00037 
00038 #include <sstream>
00039 
00040 using std::stringstream ;
00041 using std::endl ;
00042 
00043 #include "BESCatalogDirectory.h"
00044 #include "BESCatalogUtils.h"
00045 #include "BESInfo.h"
00046 #include "BESResponseException.h"
00047 #include "BESResponseNames.h"
00048 #include "BESCatalogUtils.h"
00049 #include "BESContainerStorageList.h"
00050 #include "BESContainerStorageCatalog.h"
00051 
00052 BESCatalogDirectory::BESCatalogDirectory( const string &name )
00053     : BESCatalog( name )
00054 {
00055     try
00056     {
00057         _utils = BESCatalogUtils::Utils( name ) ;
00058     }
00059     catch( BESException &e )
00060     {
00061         throw BESResponseException( e.get_message(), e.get_file(), e.get_line() ) ;
00062     }
00063 }
00064 
00065 BESCatalogDirectory::~BESCatalogDirectory( )
00066 {
00067 }
00068 
00069 bool
00070 BESCatalogDirectory::show_catalog( const string &node,
00071                                    const string &coi,
00072                                    BESInfo *info )
00073 {
00074     // remove any trailing slash
00075     string fullnode = node ;
00076     if( node != "" )
00077     {
00078         string::size_type stopat = node.length() - 1 ;
00079         while( node[stopat] == '/' )
00080         {
00081             stopat-- ;
00082         }
00083         fullnode = fullnode.substr( 0, stopat + 1 ) ;
00084     }
00085 
00086     string::size_type dotdot = fullnode.find( ".." ) ;
00087     if( dotdot != string::npos )
00088     {
00089         string s = (string)"'../' not allowed in catalog node name " + fullnode;
00090         throw BESResponseException( s, __FILE__, __LINE__ ) ;
00091     }
00092 
00093     if( fullnode == "" )
00094     {
00095         fullnode = _utils->get_root_dir() ;
00096     }
00097     else
00098     {
00099         fullnode = _utils->get_root_dir() + "/" + fullnode ;
00100     }
00101 
00102     string basename ;
00103     string::size_type slash = fullnode.rfind( "/" ) ;
00104     if( slash != string::npos )
00105     {
00106         basename = fullnode.substr( slash+1, fullnode.length() - slash ) ;
00107     }
00108     else
00109     {
00110         basename = fullnode ;
00111     }
00112 
00113     // Is this node a directory?
00114     DIR *dip = opendir( fullnode.c_str() ) ;
00115     if( dip != NULL )
00116     {
00117         // The node is a directory
00118 
00119         // if the directory requested is in the exclude list then we won't
00120         // let the user see it.
00121         if( _utils->exclude( basename ) )
00122         {
00123             return false ;
00124         }
00125         struct stat cbuf ;
00126         int statret = stat( fullnode.c_str(), &cbuf ) ;
00127         if( statret == 0 )
00128         {
00129             map<string,string> a1 ;
00130             a1["thredds_collection"] = "\"true\"" ;
00131             a1["isData"] = "\"false\"" ;
00132             info->begin_tag( "dataset", &a1 ) ;
00133             if( node == "" )
00134             {
00135                 add_stat_info( info, cbuf, "/" ) ;
00136             }
00137             else
00138             {
00139                 add_stat_info( info, cbuf, node ) ;
00140             }
00141 
00142             struct dirent *dit;
00143             unsigned int cnt = 0 ;
00144             struct stat buf;
00145             while( ( dit = readdir( dip ) ) != NULL )
00146             {
00147                 string dirEntry = dit->d_name ;
00148                 if( dirEntry != "." && dirEntry != ".." )
00149                 {
00150                     // look at the mode and determine if this is a directory
00151                     string fullPath = fullnode + "/" + dirEntry ;
00152                     statret = stat( fullPath.c_str(), &buf ) ;
00153                     if ( statret == 0 && S_ISDIR( buf.st_mode ) )
00154                     {
00155                         if( _utils->exclude( dirEntry ) == false )
00156                         {
00157                             cnt++ ;
00158                         }
00159                     }
00160                     // if it is a regular file, whether accessible or not, let's
00161                     // include it if it passes the include regular expression.
00162                     //else if ( statret == 0 && S_ISREG( buf.st_mode ) )
00163                     else
00164                     {
00165                         if( _utils->include( dirEntry ) )
00166                         {
00167                             cnt++ ;
00168                         }
00169                     }
00170                 }
00171             }
00172 
00173             stringstream sscnt ;
00174             sscnt << cnt ;
00175             info->add_tag( "count", sscnt.str() ) ;
00176 
00177             if( coi == CATALOG_RESPONSE )
00178             {
00179                 rewinddir( dip ) ;
00180 
00181                 while( ( dit = readdir( dip ) ) != NULL )
00182                 {
00183                     string dirEntry = dit->d_name ;
00184                     if( dirEntry != "." && dirEntry != ".." )
00185                     {
00186                         // look at the mode and determine if this is a directory
00187                         string fullPath = fullnode + "/" + dirEntry ;
00188                         statret = stat( fullPath.c_str(), &buf ) ;
00189                         if ( statret == 0 && S_ISDIR( buf.st_mode ) )
00190                         {
00191                             if( _utils->exclude( dirEntry ) == false )
00192                             {
00193                                 map<string,string> a2 ;
00194                                 a2["thredds_collection"] = "\"true\"" ;
00195                                 a2["isData"] = "\"false\"" ;
00196                                 a2["isAccessible"] = "\"true\"" ;
00197                                 info->begin_tag( "dataset", &a2 ) ;
00198                                 add_stat_info( info, buf, dirEntry ) ;
00199                                 info->end_tag( "dataset" ) ;
00200                             }
00201                         }
00202                         else if ( statret == 0 && S_ISREG( buf.st_mode ) )
00203                         {
00204                             if( _utils->include( dirEntry ) )
00205                             {
00206                                 map<string,string> a3 ;
00207                                 a3["thredds_collection"] = "\"false\"" ;
00208                                 list<string> provides ;
00209                                 if( isData( fullPath, provides ) )
00210                                     a3["isData"] = "\"true\"" ;
00211                                 else
00212                                     a3["isData"] = "\"false\"" ;
00213                                 a3["isAccessible"] = "\"true\"" ;
00214                                 info->begin_tag( "dataset", &a3 ) ;
00215                                 add_stat_info( info, buf, dirEntry ) ;
00216                                 info->end_tag( "dataset" ) ;
00217                             }
00218                         }
00219                         else
00220                         {
00221                             if( _utils->include( dirEntry ) )
00222                             {
00223                                 map<string,string> a3 ;
00224                                 a3["thredds_collection"] = "\"false\"" ;
00225                                 a3["isData"] = "\"false\"" ;
00226                                 a3["isAccessible"] = "\"false\"" ;
00227                                 info->begin_tag( "dataset", &a3 ) ;
00228                                 info->add_tag( "name", dirEntry ) ;
00229                                 info->end_tag( "dataset" ) ;
00230                             }
00231                         }
00232                     }
00233                 }
00234             }
00235             closedir( dip ) ;
00236             info->end_tag( "dataset" ) ;
00237         }
00238         else
00239         {
00240             map<string,string> a1 ;
00241             a1["thredds_collection"] = "\"true\"" ;
00242             a1["isData"] = "\"false\"" ;
00243             a1["isAccessible"] = "\"false\"" ;
00244             info->begin_tag( "dataset", &a1 ) ;
00245             if( node == "" )
00246                 info->add_tag( "name", "/" ) ;
00247             else
00248                 info->add_tag( "name", node ) ;
00249             info->end_tag( "dataset" ) ;
00250         }
00251     }
00252     else
00253     {
00254         // if the node is in the include list then continue, else the node
00255         // requested is not included and we return false.
00256         if( _utils->include( basename ) )
00257         {
00258             struct stat buf;
00259             int statret = stat( fullnode.c_str(), &buf ) ;
00260             if ( statret == 0 && S_ISREG( buf.st_mode ) )
00261             {
00262                 map<string,string> a4 ;
00263                 a4["thredds_collection"] = "\"false\"" ;
00264                 list<string> provides ;
00265                 if( isData( node, provides ) )
00266                     a4["isData"] = "\"true\"" ;
00267                 else
00268                     a4["isData"] = "\"false\"" ;
00269                 a4["isAccessible"] = "\"true\"" ;
00270                 info->begin_tag( "dataset", &a4 ) ;
00271                 add_stat_info( info, buf, node ) ;
00272                 info->end_tag( "dataset" ) ;
00273             }
00274             else
00275             {
00276                 return false ;
00277             }
00278         }
00279         else
00280         {
00281             return false ;
00282         }
00283     }
00284 
00285     return true ;
00286 }
00287 
00288 void
00289 BESCatalogDirectory::add_stat_info( BESInfo *info,
00290                                     struct stat &buf,
00291                                     const string &node )
00292 {
00293     info->add_tag( "name", node ) ;
00294 
00295     off_t sz = buf.st_size ;
00296     stringstream ssz ;
00297     ssz << sz ;
00298     info->add_tag( "size", ssz.str() ) ;
00299 
00300     // %T = %H:%M:%S
00301     // %F = %Y-%m-%d
00302     time_t mod = buf.st_mtime ;
00303     struct tm *stm = gmtime( &mod ) ;
00304     char mdate[64] ;
00305     strftime( mdate, 64, "%Y-%m-%d", stm ) ;
00306     char mtime[64] ;
00307     strftime( mtime, 64, "%T", stm ) ;
00308 
00309     info->begin_tag( "lastmodified" ) ;
00310 
00311     stringstream sdt ;
00312     sdt << mdate ;
00313     info->add_tag( "date", sdt.str() ) ;
00314 
00315     stringstream stt ;
00316     stt << mtime ;
00317     info->add_tag( "time", stt.str() ) ;
00318 
00319     info->end_tag( "lastmodified" ) ;
00320 }
00321 
00322 bool
00323 BESCatalogDirectory::isData( const string &inQuestion,
00324                              list<string> &provides )
00325 {
00326     BESContainerStorage *store =
00327         BESContainerStorageList::TheList()->find_persistence( get_catalog_name() ) ;
00328     if( !store )
00329         return false ;
00330 
00331     BESContainerStorageCatalog *cat_store =
00332         dynamic_cast<BESContainerStorageCatalog *>(store ) ;
00333     if( !cat_store )
00334         return false ;
00335 
00336     return cat_store->isData( inQuestion, provides ) ;
00337 }
00338 
00346 void
00347 BESCatalogDirectory::dump( ostream &strm ) const
00348 {
00349     strm << BESIndent::LMarg << "BESCatalogDirectory::dump - ("
00350                              << (void *)this << ")" << endl ;
00351     BESIndent::Indent() ;
00352 
00353     strm << BESIndent::LMarg << "catalog utilities: " << endl ;
00354     BESIndent::Indent() ;
00355     _utils->dump( strm ) ;
00356     BESIndent::UnIndent() ;
00357     BESIndent::UnIndent() ;
00358 }
00359 

Generated on Sat Jan 19 04:05:36 2008 for OPeNDAP Back End Server (BES) by  doxygen 1.5.4