00001
00002
00003
00004
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
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
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
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, 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
00177 setConsumer( xml::parseDefAssign() >> bind( &ProductNode::done, this, _1 ) );
00178
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
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
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, 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;
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 }
00286 }