libzypp  10.5.0
ContentFileReader.cc
Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #include <iostream>
00013 #include <sstream>
00014 
00015 #include "zypp/base/LogTools.h"
00016 #include "zypp/base/String.h"
00017 #include "zypp/base/IOStream.h"
00018 #include "zypp/base/UserRequestException.h"
00019 #include "zypp/parser/ParseException.h"
00020 
00021 #include "zypp/parser/susetags/ContentFileReader.h"
00022 #include "zypp/parser/susetags/RepoIndex.h"
00023 
00024 using std::endl;
00025 #undef  ZYPP_BASE_LOGGER_LOGGROUP
00026 #define ZYPP_BASE_LOGGER_LOGGROUP "parser::susetags"
00027 
00029 namespace zypp
00030 { 
00031 
00032   namespace parser
00033   { 
00034 
00035     namespace susetags
00036     { 
00037 
00039       //
00040       //        CLASS NAME : ContentFileReader::Impl
00041       //
00043       struct ContentFileReader::Impl
00044       {
00045         public:
00046           Impl( const ContentFileReader & parent_r )
00047           : _parent( parent_r )
00048           {}
00049 
00050           RepoIndex & repoindex()
00051           {
00052             if ( !_repoindex )
00053               _repoindex = new RepoIndex;
00054             return *_repoindex;
00055           }
00056 
00057           bool hasRepoIndex() const
00058           { return _repoindex; }
00059 
00060           RepoIndex_Ptr handoutRepoIndex()
00061           {
00062             RepoIndex_Ptr ret;
00063             ret.swap( _repoindex );
00064             _repoindex = 0;
00065             return ret;
00066           }
00067 
00068         public:
00069           bool setFileCheckSum( std::map<std::string, CheckSum> & map_r, const std::string & value ) const
00070           {
00071             bool error = false;
00072             std::vector<std::string> words;
00073             if ( str::split( value, std::back_inserter( words ) ) == 3 )
00074             {
00075               map_r[words[2]] = CheckSum( words[0], words[1] );
00076             }
00077             else
00078             {
00079               error = true;
00080             }
00081             return error;
00082           }
00083 
00084         public:
00085           std::string _inputname;
00086 
00087         private:
00088           const ContentFileReader & _parent;
00089           RepoIndex_Ptr      _repoindex;
00090       };
00092 
00094       //
00095       //        CLASS NAME : ContentFileReader
00096       //
00098 
00100       //
00101       //        METHOD NAME : ContentFileReader::ContentFileReader
00102       //        METHOD TYPE : Ctor
00103       //
00104       ContentFileReader::ContentFileReader()
00105       {}
00106 
00108       //
00109       //        METHOD NAME : ContentFileReader::~ContentFileReader
00110       //        METHOD TYPE : Dtor
00111       //
00112       ContentFileReader::~ContentFileReader()
00113       {}
00114 
00116       //
00117       //        METHOD NAME : ContentFileReader::beginParse
00118       //        METHOD TYPE : void
00119       //
00120       void ContentFileReader::beginParse()
00121       {
00122         _pimpl.reset( new Impl(*this) );
00123         // actually mandatory, but in case they were forgotten...
00124         _pimpl->repoindex().descrdir = "suse/setup/descr";
00125         _pimpl->repoindex().datadir = "suse";
00126       }
00127 
00129       //
00130       //        METHOD NAME : ContentFileReader::endParse
00131       //        METHOD TYPE : void
00132       //
00133       void ContentFileReader::endParse()
00134       {
00135         // consume oldData
00136         if ( _pimpl->hasRepoIndex() )
00137         {
00138           if ( _repoIndexConsumer )
00139             _repoIndexConsumer( _pimpl->handoutRepoIndex() );
00140         }
00141 
00142         MIL << "[Content]" << endl;
00143         _pimpl.reset();
00144       }
00145 
00147       //
00148       //        METHOD NAME : ContentFileReader::userRequestedAbort
00149       //        METHOD TYPE : void
00150       //
00151       void ContentFileReader::userRequestedAbort( unsigned lineNo_r )
00152       {
00153         ZYPP_THROW( AbortRequestException( errPrefix( lineNo_r ) ) );
00154       }
00155 
00157       //
00158       //        METHOD NAME : ContentFileReader::errPrefix
00159       //        METHOD TYPE : std::string
00160       //
00161       std::string ContentFileReader::errPrefix( unsigned lineNo_r,
00162                                                 const std::string & msg_r,
00163                                                 const std::string & line_r ) const
00164       {
00165         return str::form( "%s:%u:%s | %s",
00166                           _pimpl->_inputname.c_str(),
00167                           lineNo_r,
00168                           line_r.c_str(),
00169                           msg_r.c_str() );
00170       }
00171 
00173       //
00174       //        METHOD NAME : ContentFileReader::parse
00175       //        METHOD TYPE : void
00176       //
00177       void ContentFileReader::parse( const InputStream & input_r,
00178                                      const ProgressData::ReceiverFnc & fnc_r )
00179       {
00180         MIL << "Start parsing content repoindex" << input_r << endl;
00181         if ( ! input_r.stream() )
00182         {
00183           std::ostringstream s;
00184           s << "Can't read bad stream: " << input_r;
00185           ZYPP_THROW( ParseException( s.str() ) );
00186         }
00187         beginParse();
00188         _pimpl->_inputname = input_r.name();
00189 
00190         ProgressData ticks( makeProgressData( input_r ) );
00191         ticks.sendTo( fnc_r );
00192         if ( ! ticks.toMin() )
00193           userRequestedAbort( 0 );
00194 
00195         iostr::EachLine line( input_r );
00196         for( ; line; line.next() )
00197         {
00198           // strip 1st word from line to separate tag and value.
00199           std::string value( *line );
00200           std::string key( str::stripFirstWord( value, /*ltrim_first*/true ) );
00201 
00202           if ( key.empty() || *key.c_str() == '#' ) // empty or comment line
00203           {
00204             continue;
00205           }
00206 
00207           // strip modifier if exists
00208           std::string modifier;
00209           std::string::size_type pos = key.rfind( '.' );
00210           if ( pos != std::string::npos )
00211           {
00212             modifier = key.substr( pos+1 );
00213             key.erase( pos );
00214           }
00215 
00216           //
00217           // ReppoIndex related data:
00218           //
00219           else if ( key == "DESCRDIR" )
00220           {
00221             _pimpl->repoindex().descrdir = value;
00222           }
00223           else if ( key == "DATADIR" )
00224           {
00225             _pimpl->repoindex().datadir = value;
00226           }
00227           else if ( key == "KEY" )
00228           {
00229             if ( _pimpl->setFileCheckSum( _pimpl->repoindex().signingKeys, value ) )
00230             {
00231               ZYPP_THROW( ParseException( errPrefix( line.lineNo(), "Expected [KEY algorithm checksum filename]", *line ) ) );
00232             }
00233           }
00234           else if ( key == "META" )
00235           {
00236             if ( _pimpl->setFileCheckSum( _pimpl->repoindex().metaFileChecksums, value ) )
00237             {
00238               ZYPP_THROW( ParseException( errPrefix( line.lineNo(), "Expected [algorithm checksum filename]", *line ) ) );
00239             }
00240           }
00241           else if ( key == "HASH" )
00242           {
00243             if ( _pimpl->setFileCheckSum( _pimpl->repoindex().mediaFileChecksums, value ) )
00244             {
00245               ZYPP_THROW( ParseException( errPrefix( line.lineNo(), "Expected [algorithm checksum filename]", *line ) ) );
00246             }
00247           }
00248           else
00249           {
00250             DBG << errPrefix( line.lineNo(), "ignored", *line ) << endl;
00251           }
00252 
00253 
00254           if ( ! ticks.set( input_r.stream().tellg() ) )
00255             userRequestedAbort( line.lineNo() );
00256         }
00257 
00258         //
00259         // post processing
00260         //
00261         if ( ! ticks.toMax() )
00262           userRequestedAbort( line.lineNo() );
00263 
00264         endParse();
00265         MIL << "Done parsing " << input_r << endl;
00266       }
00267 
00269     } // namespace susetags
00272   } // namespace parser
00275 } // namespace zypp