libzypp  10.5.0
ProductFileReader.cc
Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #include <iostream>
00013 #include "zypp/base/Logger.h"
00014 #include "zypp/base/Exception.h"
00015 #include "zypp/base/Functional.h"
00016 
00017 #include "zypp/PathInfo.h"
00018 
00019 #include "zypp/parser/ProductFileReader.h"
00020 #include "zypp/parser/xml/ParseDef.h"
00021 #include "zypp/parser/xml/ParseDefConsume.h"
00022 #include "zypp/parser/xml/Reader.h"
00023 
00024 using std::endl;
00025 
00027 namespace zypp
00028 { 
00029 
00030   namespace parser
00031   { 
00032 
00034     //
00035     // class ProductFileData::Upgrade
00036     //
00038 
00039     struct ProductFileData::Upgrade::Impl
00040     {
00041       std::string                 _name;
00042       std::string                 _summary;
00043       std::string                 _repository;
00044       std::string                 _product;
00045       DefaultIntegral<bool,false> _notify;
00046       std::string                 _status;
00047     };
00048 
00049     ProductFileData::Upgrade::Upgrade( Impl * allocated_r )
00050       : _pimpl( allocated_r ? allocated_r : new Impl )
00051     {}
00052 
00053     std::string ProductFileData::Upgrade::name()       const { return _pimpl->_name; }
00054     std::string ProductFileData::Upgrade::summary()    const { return _pimpl->_summary; }
00055     std::string ProductFileData::Upgrade::repository() const { return _pimpl->_repository; }
00056     std::string ProductFileData::Upgrade::product()    const { return _pimpl->_product; }
00057     bool        ProductFileData::Upgrade::notify()     const { return _pimpl->_notify; }
00058     std::string ProductFileData::Upgrade::status()     const { return _pimpl->_status; }
00059 
00061     //
00062     // class ProductFileData
00063     //
00065 
00066     struct ProductFileData::Impl
00067     {
00068       IdString    _vendor;
00069       IdString    _name;
00070       Edition     _edition;
00071       Arch        _arch;
00072 
00073       std::string _shortName;
00074       std::string _summary;
00075 
00076       std::string _productline;
00077       std::string _registerTarget;
00078       std::string _registerRelease;
00079 
00080       std::string _updaterepokey;
00081 
00082       Upgrades    _upgrades;
00083     };
00084 
00085     ProductFileData::ProductFileData( Impl * allocated_r )
00086       : _pimpl( allocated_r ? allocated_r : new Impl )
00087     {}
00088 
00089     IdString    ProductFileData::vendor()  const { return _pimpl->_vendor; }
00090     IdString    ProductFileData::name()    const { return _pimpl->_name; }
00091     Edition     ProductFileData::edition() const { return _pimpl->_edition; }
00092     Arch        ProductFileData::arch()    const { return _pimpl->_arch; }
00093 
00094     std::string ProductFileData::shortName()    const { return _pimpl->_shortName; }
00095     std::string ProductFileData::summary()      const { return _pimpl->_summary; }
00096 
00097     std::string ProductFileData::productline()     const { return _pimpl->_productline; }
00098     std::string ProductFileData::registerTarget()  const { return _pimpl->_registerTarget; }
00099     std::string ProductFileData::registerRelease() const { return _pimpl->_registerRelease; }
00100 
00101     std::string ProductFileData::updaterepokey() const { return _pimpl->_updaterepokey; }
00102 
00103     const ProductFileData::Upgrades & ProductFileData::upgrades() const { return _pimpl->_upgrades; }
00104 
00105     std::ostream & operator<<( std::ostream & str, const ProductFileData & obj )
00106     {
00107       str << str::form( "|product|%s|%s|%s|%s|",
00108                         obj.name().c_str(),
00109                         obj.edition().c_str(),
00110                         obj.arch().c_str(),
00111                         obj.vendor().c_str() );
00112       if ( ! obj.upgrades().empty() )
00113       {
00114         for_( it, obj.upgrades().begin(), obj.upgrades().end() )
00115           str << endl << "    " << *it;
00116       }
00117       return str;
00118     }
00119 
00120     std::ostream & operator<<( std::ostream & str, const ProductFileData::Upgrade & obj )
00121     {
00122       str << str::form( "|upgrade|%s|%s|%s|%s|%s|",
00123                         obj.name().c_str(),
00124                         obj.repository().c_str(),
00125                         obj.product().c_str(),
00126                         obj.status().c_str(),
00127                         (obj.notify() ? "notify" : "noNotify") );
00128       return str;
00129     }
00131     //
00132     // class ProductFileReader
00133     //
00135 
00136     struct ProductNode : public xml::ParseDef
00137     {
00138       ProductNode( ProductFileData::Impl & pdata_r )
00139         : ParseDef( "product", MANDTAORY )
00140         , _pdata( pdata_r )
00141       {
00142         (*this)
00143             ("vendor",        OPTIONAL,   xml::parseDefAssign( _pdata._vendor ) )
00144             ("name",          MANDTAORY,  xml::parseDefAssign( _pdata._name ) )
00145             ("version",       MANDTAORY,  xml::parseDefAssign( _version ) )
00146             ("release",       MANDTAORY,  xml::parseDefAssign( _release ) )
00147             ("arch",          MANDTAORY,  xml::parseDefAssign( _pdata._arch ) )
00148             ("shortsummary",  OPTIONAL,   xml::parseDefAssign( _pdata._shortName ) )
00149             ("summary",       MULTIPLE_OPTIONAL, xml::parseDefAssign( _ttext )( "lang", _tlocale )
00150                                           >>bind( &ProductNode::doneLocalizedDefault, this, _1, boost::ref(_pdata._summary) ))
00151             ("productline",   OPTIONAL,   xml::parseDefAssign( _pdata._productline ) )
00152             ("register",      OPTIONAL)
00153             ("updaterepokey", OPTIONAL,   xml::parseDefAssign( _pdata._updaterepokey ) )
00154             ("upgrades",      OPTIONAL)
00155             ;
00156 
00157         (*this)["register"]
00158             ("target",        OPTIONAL,   xml::parseDefAssign( _pdata._registerTarget ) )
00159             ("release",       OPTIONAL,   xml::parseDefAssign( _pdata._registerRelease ) )
00160             ;
00161 
00162         (*this)["upgrades"]
00163             ("upgrade",       MULTIPLE_OPTIONAL, xml::parseDefAssign()
00164                                                  >> bind( &ProductNode::doneUpgrade, this, _1 ))
00165             ;
00166 
00167         (*this)["upgrades"]["upgrade"]
00168             ("name",          OPTIONAL,   xml::parseDefAssign( _upgrade._name ) )
00169             ("summary",       OPTIONAL,   xml::parseDefAssign( _upgrade._summary ) )
00170             ("repository",    OPTIONAL,   xml::parseDefAssign( _upgrade._repository ) )
00171             ("product",       OPTIONAL,   xml::parseDefAssign( _upgrade._product ) )
00172             ("notify",        OPTIONAL,   xml::parseDefAssign( _upgrade._notify ) )
00173             ("status",        OPTIONAL,   xml::parseDefAssign( _upgrade._status ) )
00174             ;
00175 
00176         // </product> callback to build edition.
00177         setConsumer( xml::parseDefAssign() >> bind( &ProductNode::done, this, _1 ) );
00178         // xml::ParseDef::_debug = true;
00179       }
00180 
00182       void doneUpgrade( const xml::Node & _node )
00183       {
00184         ProductFileData::Upgrade cdata( new ProductFileData::Upgrade::Impl( _upgrade ) );
00185         _pdata._upgrades.push_back( cdata );
00186         _upgrade = ProductFileData::Upgrade::Impl();
00187       }
00189       void doneLocalizedDefault( const xml::Node & _node, std::string & store_r )
00190       {
00191         // take 1st or default
00192         if ( store_r.empty() || _tlocale.empty() )
00193           store_r = _ttext;
00194       }
00195 
00197       void done( const xml::Node & _node )
00198       {
00199         _pdata._edition = Edition( _version, _release );
00200       }
00201 
00202       private:
00203         ProductFileData::Impl & _pdata;
00204 
00205         std::string             _version;
00206         std::string             _release;
00207 
00208         std::string             _ttext;
00209         std::string             _tlocale;
00210 
00211         ProductFileData::Upgrade::Impl _upgrade;
00212     };
00213 
00214     bool ProductFileReader::parse( const InputStream & input_r ) const
00215     {
00216       MIL << "+++" << input_r << endl;
00217       bool ret = true;
00218 
00219       ProductFileData::Impl * pdataImpl = 0;
00220       ProductFileData pdata( (pdataImpl = new ProductFileData::Impl) );
00221 
00222       try
00223       {
00224         xml::Reader reader( input_r );
00225         ProductNode rootNode( *pdataImpl );
00226         rootNode.take( reader );
00227 
00228       }
00229       catch ( const Exception & err )
00230       {
00231         // parse error
00232         ERR << err << endl;
00233         ERR << "---" << ret << " - " << input_r << endl;
00234         return ret;
00235       }
00236 
00237       if ( _consumer )
00238       {
00239         ret = _consumer( pdata );
00240       }
00241 
00242       MIL << "---" << ret << " - " << input_r << endl;
00243       return ret;
00244     }
00245 
00247 
00248     bool ProductFileReader::scanDir( const Consumer & consumer_r, const Pathname & dir_r )
00249     {
00250       std::list<Pathname> retlist;
00251       int res = filesystem::readdir( retlist, dir_r, /*dots*/false );
00252       if ( res != 0 )
00253       {
00254         WAR << "scanDir " << dir_r << " failed (" << res << ")" << endl;
00255         return true;
00256       }
00257 
00258       ProductFileReader reader( consumer_r );
00259       for_( it, retlist.begin(), retlist.end() )
00260       {
00261         if ( PathInfo( *it, PathInfo::LSTAT ).isFile() && ! reader.parse( *it ) )
00262         {
00263           return false; // consumer_r request to stop parsing.
00264         }
00265       }
00266       return true;
00267     }
00268 
00269     ProductFileData ProductFileReader::scanFile( const Pathname & file_r )
00270     {
00271       if ( ! PathInfo( file_r ).isFile() )
00272       {
00273         WAR << "scanFile " << PathInfo( file_r ) << " is not a file." << endl;
00274         return ProductFileData();
00275       }
00276 
00277       ProductFileData ret;
00278       ProductFileReader reader( functor::getFirst( ret ), file_r );
00279       return ret;
00280    }
00281 
00283   } // namespace parser
00286 } // namespace zypp