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 Atmostpheric 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     DIR *dip = opendir( fullnode.c_str() ) ;
00113     if( dip != NULL )
00114     {
00115         // if the directory requested is in the exclude list then we won't
00116         // let the user see it.
00117         if( _utils->exclude( basename ) )
00118         {
00119             return false ;
00120         }
00121         struct stat cbuf ;
00122         stat( fullnode.c_str(), &cbuf ) ;
00123         map<string,string> a1 ;
00124         a1["thredds_collection"] = "\"true\"" ;
00125         a1["isData"] = "\"false\"" ;
00126         info->begin_tag( "dataset", &a1 ) ;
00127         if( node == "" )
00128         {
00129             add_stat_info( info, cbuf, "/" ) ;
00130         }
00131         else
00132         {
00133             add_stat_info( info, cbuf, node ) ;
00134         }
00135 
00136         struct dirent *dit;
00137         unsigned int cnt = 0 ;
00138         struct stat buf;
00139         while( ( dit = readdir( dip ) ) != NULL )
00140         {
00141             string dirEntry = dit->d_name ;
00142             if( dirEntry != "." && dirEntry != ".." )
00143             {
00144                 // look at the mode and determine if this is a directory
00145                 string fullPath = fullnode + "/" + dirEntry ;
00146                 stat( fullPath.c_str(), &buf ) ;
00147                 if ( S_ISDIR( buf.st_mode ) )
00148                 {
00149                     if( _utils->exclude( dirEntry ) == false )
00150                     {
00151                         cnt++ ;
00152                     }
00153                 }
00154                 else if ( S_ISREG( buf.st_mode ) )
00155                 {
00156                     if( _utils->include( dirEntry ) )
00157                     {
00158                         cnt++ ;
00159                     }
00160                 }
00161             }
00162         }
00163 
00164         stringstream sscnt ;
00165         sscnt << cnt ;
00166         info->add_tag( "count", sscnt.str() ) ;
00167 
00168         if( coi == CATALOG_RESPONSE )
00169         {
00170             rewinddir( dip ) ;
00171 
00172             while( ( dit = readdir( dip ) ) != NULL )
00173             {
00174                 string dirEntry = dit->d_name ;
00175                 if( dirEntry != "." && dirEntry != ".." )
00176                 {
00177                     // look at the mode and determine if this is a directory
00178                     string fullPath = fullnode + "/" + dirEntry ;
00179                     stat( fullPath.c_str(), &buf ) ;
00180                     if ( S_ISDIR( buf.st_mode ) )
00181                     {
00182                         if( _utils->exclude( dirEntry ) == false )
00183                         {
00184                             map<string,string> a2 ;
00185                             a2["thredds_collection"] = "\"true\"" ;
00186                             a2["isData"] = "\"false\"" ;
00187                             info->begin_tag( "dataset", &a2 ) ;
00188                             add_stat_info( info, buf, dirEntry ) ;
00189                             info->end_tag( "dataset" ) ;
00190                         }
00191                     }
00192                     else if ( S_ISREG( buf.st_mode ) )
00193                     {
00194                         if( _utils->include( dirEntry ) )
00195                         {
00196                             map<string,string> a3 ;
00197                             a3["thredds_collection"] = "\"false\"" ;
00198                             list<string> provides ;
00199                             if( isData( dirEntry, provides ) )
00200                                 a3["isData"] = "\"true\"" ;
00201                             else
00202                                 a3["isData"] = "\"false\"" ;
00203                             info->begin_tag( "dataset", &a3 ) ;
00204                             add_stat_info( info, buf, dirEntry ) ;
00205                             info->end_tag( "dataset" ) ;
00206                         }
00207                     }
00208                 }
00209             }
00210         }
00211         closedir( dip ) ;
00212         info->end_tag( "dataset" ) ;
00213     }
00214     else
00215     {
00216         // if the node is in the include list then continue, else the node
00217         // requested is not included and we return false.
00218         if( _utils->include( basename ) )
00219         {
00220             struct stat buf;
00221             int statret = stat( fullnode.c_str(), &buf ) ;
00222             if ( statret == 0 && S_ISREG( buf.st_mode ) )
00223             {
00224                 map<string,string> a4 ;
00225                 a4["thredds_collection"] = "\"false\"" ;
00226                 list<string> provides ;
00227                 if( isData( node, provides ) )
00228                     a4["isData"] = "\"true\"" ;
00229                 else
00230                     a4["isData"] = "\"false\"" ;
00231                 info->begin_tag( "dataset", &a4 ) ;
00232                 add_stat_info( info, buf, node ) ;
00233                 info->end_tag( "dataset" ) ;
00234             }
00235             else
00236             {
00237                 return false ;
00238             }
00239         }
00240         else
00241         {
00242             return false ;
00243         }
00244     }
00245 
00246     return true ;
00247 }
00248 
00249 void
00250 BESCatalogDirectory::add_stat_info( BESInfo *info,
00251                                     struct stat &buf,
00252                                     const string &node )
00253 {
00254     info->add_tag( "name", node ) ;
00255 
00256     off_t sz = buf.st_size ;
00257     stringstream ssz ;
00258     ssz << sz ;
00259     info->add_tag( "size", ssz.str() ) ;
00260 
00261     // %T = %H:%M:%S
00262     // %F = %Y-%m-%d
00263     time_t mod = buf.st_mtime ;
00264     struct tm *stm = gmtime( &mod ) ;
00265     char mdate[64] ;
00266     strftime( mdate, 64, "%Y-%m-%d", stm ) ;
00267     char mtime[64] ;
00268     strftime( mtime, 64, "%T", stm ) ;
00269 
00270     info->begin_tag( "lastmodified" ) ;
00271 
00272     stringstream sdt ;
00273     sdt << mdate ;
00274     info->add_tag( "date", sdt.str() ) ;
00275 
00276     stringstream stt ;
00277     stt << mtime ;
00278     info->add_tag( "time", stt.str() ) ;
00279 
00280     info->end_tag( "lastmodified" ) ;
00281 }
00282 
00283 bool
00284 BESCatalogDirectory::isData( const string &inQuestion,
00285                              list<string> &provides )
00286 {
00287     BESContainerStorage *store =
00288         BESContainerStorageList::TheList()->find_persistence( get_catalog_name() ) ;
00289     if( !store )
00290         return false ;
00291 
00292     BESContainerStorageCatalog *cat_store =
00293         dynamic_cast<BESContainerStorageCatalog *>(store ) ;
00294     if( !cat_store )
00295         return false ;
00296 
00297     return cat_store->isData( inQuestion, provides ) ;
00298 }
00299 
00307 void
00308 BESCatalogDirectory::dump( ostream &strm ) const
00309 {
00310     strm << BESIndent::LMarg << "BESCatalogDirectory::dump - ("
00311                              << (void *)this << ")" << endl ;
00312     BESIndent::Indent() ;
00313 
00314     strm << BESIndent::LMarg << "catalog utilities: " << endl ;
00315     BESIndent::Indent() ;
00316     _utils->dump( strm ) ;
00317     BESIndent::UnIndent() ;
00318     BESIndent::UnIndent() ;
00319 }
00320 

Generated on Wed Aug 29 03:20:58 2007 for OPeNDAP Back End Server (BES) by  doxygen 1.5.2