00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013 #include <functional>
00014 #include <set>
00015 #include <map>
00016
00017 #include <ext/hash_set>
00018 #include <ext/hash_fun.h>
00019
00020 #include "zypp/base/Logger.h"
00021 #include "zypp/base/Exception.h"
00022 #include "zypp/base/String.h"
00023 #include "zypp/base/Counter.h"
00024
00025 #include "zypp/CapFactory.h"
00026 #include "zypp/capability/Capabilities.h"
00027
00028 using std::endl;
00029
00031 namespace
00032 {
00033 using ::zypp::Resolvable;
00034 using ::zypp::capability::CapabilityImpl;
00035 using ::zypp::capability::CapImplOrder;
00036
00037 struct CapImplHashFun
00038 {
00039 size_t operator() ( const CapabilityImpl::Ptr & p ) const
00040 {
00041 return __gnu_cxx::hash<const char*>()( p->encode().c_str() );
00042 }
00043 };
00044
00045 struct CapImplHashEqual
00046 {
00047 bool operator() ( const CapabilityImpl::Ptr & lhs, const CapabilityImpl::Ptr & rhs ) const
00048 {
00049 return ( lhs->encode() == rhs->encode()
00050 && lhs->kind() == rhs->kind()
00051 && lhs->refers() == rhs->refers() );
00052 }
00053 };
00054
00056
00057 typedef __gnu_cxx::hash_set<CapabilityImpl::Ptr, CapImplHashFun, CapImplHashEqual> USet;
00058
00059
00066 USet _uset;
00067
00077 CapabilityImpl::Ptr usetInsert( CapabilityImpl * allocated_r )
00078 {
00079 return *(_uset.insert( CapabilityImpl::Ptr(allocated_r) ).first);
00080 }
00081
00085 struct USetStatsCollect : public std::unary_function<CapabilityImpl::constPtr, void>
00086 {
00087 typedef ::zypp::Counter<unsigned> Counter;
00088
00089 Counter _caps;
00090 std::map<CapabilityImpl::Kind,Counter> _capKind;
00091 std::map<Resolvable::Kind,Counter> _capRefers;
00092
00093 void operator()( const CapabilityImpl::constPtr & cap_r )
00094 {
00095
00096 ++_caps;
00097 ++(_capKind[cap_r->kind()]);
00098 ++(_capRefers[cap_r->refers()]);
00099 }
00100
00101 std::ostream & dumpOn( std::ostream & str ) const
00102 {
00103 str << " Capabilities total: " << _caps << endl;
00104 str << " Capability kinds:" << endl;
00105 for ( std::map<CapabilityImpl::Kind,Counter>::const_iterator it = _capKind.begin();
00106 it != _capKind.end(); ++it )
00107 {
00108 str << " " << it->first << '\t' << it->second << endl;
00109 }
00110 str << " Capability refers:" << endl;
00111 for ( std::map<Resolvable::Kind,Counter>::const_iterator it = _capRefers.begin();
00112 it != _capRefers.end(); ++it )
00113 {
00114 str << " " << it->first << '\t' << it->second << endl;
00115 }
00116 return str;
00117 }
00118 };
00119
00121 }
00123
00125 namespace zypp
00126 {
00127
00129
00130
00131
00149 struct CapFactory::Impl
00150 {
00152 static void assertResKind( const Resolvable::Kind & refers_r )
00153 {
00154 if ( refers_r == Resolvable::Kind() )
00155 ZYPP_THROW( Exception("Missing or empty Resolvable::Kind in Capability") );
00156 }
00157
00167 static bool isEditionSpec( Rel op_r, const Edition & edition_r )
00168 {
00169 switch ( op_r.inSwitch() )
00170 {
00171 case Rel::ANY_e:
00172 if ( edition_r != Edition::noedition )
00173 WAR << "Operator " << op_r << " causes Edition "
00174 << edition_r << " to be ignored." << endl;
00175 return false;
00176 break;
00177
00178 case Rel::NONE_e:
00179 ZYPP_THROW( Exception("Operator NONE is not allowed in Capability") );
00180 break;
00181
00182 case Rel::EQ_e:
00183 case Rel::NE_e:
00184 case Rel::LT_e:
00185 case Rel::LE_e:
00186 case Rel::GT_e:
00187 case Rel::GE_e:
00188 return true;
00189 break;
00190 }
00191
00192 ZYPP_THROW( Exception("Unknow Operator NONE is not allowed in Capability") );
00193 return false;
00194 }
00195
00197 static bool isFileSpec( const std::string & name_r )
00198 {
00199 return *name_r.c_str() == '/';
00200 }
00201
00203 static bool isSplitSpec( const std::string & name_r )
00204 {
00205 return name_r.find( ":/" ) != std::string::npos;
00206 }
00207
00209 static bool isHalSpec( const std::string & name_r )
00210 {
00211 return name_r.substr(0,4) == "hal(";
00212 }
00213
00215 static bool isModaliasSpec( const std::string & name_r )
00216 {
00217 return name_r.substr(0,9) == "modalias(";
00218 }
00219
00220 static CapabilityImpl::Ptr buildFile( const Resolvable::Kind & refers_r,
00221 const std::string & name_r )
00222 {
00223
00224 if ( name_r.empty() )
00225 {
00226
00227 return capability::NullCap::instance();
00228 }
00229
00230 assertResKind( refers_r );
00231
00232 return usetInsert
00233 ( new capability::FileCap( refers_r, name_r ) );
00234 }
00235
00242 static CapabilityImpl::Ptr buildNamed( const Resolvable::Kind & refers_r,
00243 const std::string & name_r )
00244 {
00245
00246 if ( name_r.empty() )
00247 {
00248
00249 return capability::NullCap::instance();
00250 }
00251
00252 assertResKind( refers_r );
00253
00254
00255 if ( isFileSpec( name_r ) )
00256 return usetInsert
00257 ( new capability::FileCap( refers_r, name_r ) );
00258
00259
00260 static const str::regex rx( "([^/]*):(/.*)" );
00261 str::smatch what;
00262 if( str::regex_match( name_r.begin(), name_r.end(), what, rx ) )
00263 {
00264 return usetInsert
00265 ( new capability::SplitCap( refers_r, what[1].str(), what[2].str() ) );
00266 }
00267
00268
00269 return usetInsert
00270 ( new capability::NamedCap( refers_r, name_r ) );
00271 }
00272
00281 static CapabilityImpl::Ptr buildVersioned( const Resolvable::Kind & refers_r,
00282 const std::string & name_r,
00283 Rel op_r,
00284 const Edition & edition_r )
00285 {
00286 if ( Impl::isEditionSpec( op_r, edition_r ) )
00287 {
00288 assertResKind( refers_r );
00289
00290
00291 return usetInsert
00292 ( new capability::VersionedCap( refers_r, name_r, op_r, edition_r ) );
00293 }
00294
00295
00296
00297 return buildNamed( refers_r, name_r );
00298 }
00299
00308 static CapabilityImpl::Ptr buildHal( const Resolvable::Kind & refers_r,
00309 const std::string & name_r,
00310 Rel op_r = Rel::ANY,
00311 const std::string & value_r = std::string() )
00312 {
00313 if ( op_r != Rel::ANY )
00314 {
00315 ZYPP_THROW( Exception("Unsupported kind of Hal Capability '" + op_r.asString() + "'") );
00316 }
00317
00318
00319 static const str::regex rx( "hal\\(([^)]*)\\)" );
00320 str::smatch what;
00321 if( str::regex_match( name_r.begin(), name_r.end(), what, rx ) )
00322 {
00323
00324 return usetInsert
00325 ( new capability::HalCap( ResTraits<SystemResObject>::kind,
00326 what[1].str() ) );
00327 }
00328
00329 ZYPP_THROW( Exception("Unsupported kind of Hal Capability '" + name_r + "'") );
00330 return NULL;
00331 }
00332
00333
00342 static CapabilityImpl::Ptr buildModalias( const Resolvable::Kind & refers_r,
00343 const std::string & name_r,
00344 Rel op_r = Rel::ANY,
00345 const std::string & value_r = std::string() )
00346 {
00347
00348 static const str::regex rx( "modalias\\(([^)]*)\\)" );
00349 str::smatch what;
00350 if( str::regex_match( name_r.begin(), name_r.end(), what, rx ) )
00351 {
00352
00353 return usetInsert
00354 ( new capability::ModaliasCap( ResTraits<SystemResObject>::kind,
00355 what[1].str(), op_r, value_r ) );
00356 }
00357
00358 ZYPP_THROW( Exception("Unsupported kind of Modalias Capability'" + name_r + "'") );
00359 return NULL;
00360 }
00361 };
00363
00365
00367
00368
00369
00371
00373
00374
00375
00376
00377 CapFactory::CapFactory()
00378 {}
00379
00381
00382
00383
00384
00385 CapFactory::~CapFactory()
00386 {}
00387
00389
00390
00391
00392
00393 Capability CapFactory::parse( const Resolvable::Kind & refers_r,
00394 const std::string & strval_r ) const
00395
00396 try
00397 {
00398 if ( Impl::isHalSpec( strval_r ) )
00399 {
00400 return Capability( Impl::buildHal( refers_r, strval_r ) );
00401 }
00402 if ( Impl::isModaliasSpec( strval_r ) )
00403 {
00404 return Capability( Impl::buildModalias( refers_r, strval_r ) );
00405 }
00406 if ( Impl::isFileSpec( strval_r ) )
00407 {
00408 return Capability( Impl::buildFile( refers_r, strval_r ) );
00409 }
00410
00411
00412
00413 static const str::regex rx( "(.*[^ \t])([ \t]+)([^ \t]+)([ \t]+)([^ \t]+)" );
00414 str::smatch what;
00415 if( str::regex_match( strval_r.begin(), strval_r.end(),what, rx ) )
00416 {
00417 Rel op;
00418 Edition edition;
00419 try
00420 {
00421 op = Rel(what[3].str());
00422 edition = Edition(what[5].str());
00423 }
00424 catch ( Exception & excpt )
00425 {
00426
00427 ZYPP_CAUGHT( excpt );
00428 DBG << "Trying named cap for: " << strval_r << endl;
00429
00430 return Capability( Impl::buildNamed( refers_r, strval_r ) );
00431 }
00432
00433
00434 return Capability ( Impl::buildVersioned( refers_r,
00435 what[1].str(), op, edition ) );
00436 }
00437
00438
00439 return Capability( Impl::buildNamed( refers_r, strval_r ) );
00440 }
00441 catch ( Exception & excpt )
00442 {
00443 ZYPP_RETHROW( excpt );
00444 return Capability();
00445 }
00446
00447
00449
00450
00451
00452
00453 Capability CapFactory::parse( const Resolvable::Kind & refers_r,
00454 const std::string & name_r,
00455 const std::string & op_r,
00456 const std::string & edition_r ) const
00457 try
00458 {
00459 if ( Impl::isHalSpec( name_r ) )
00460 {
00461 return Capability( Impl::buildHal( refers_r, name_r, Rel(op_r), edition_r ) );
00462 }
00463 if ( Impl::isModaliasSpec( name_r ) )
00464 {
00465 return Capability( Impl::buildModalias( refers_r, name_r, Rel(op_r), edition_r ) );
00466 }
00467
00468 return parse( refers_r, name_r, Rel(op_r), Edition(edition_r) );
00469 }
00470 catch ( Exception & excpt )
00471 {
00472 ZYPP_RETHROW( excpt );
00473 return Capability();
00474 }
00475
00477
00478
00479
00480
00481 Capability CapFactory::parse( const Resolvable::Kind & refers_r,
00482 const std::string & name_r,
00483 Rel op_r,
00484 const Edition & edition_r ) const
00485 try
00486 {
00487 if ( Impl::isHalSpec( name_r ) )
00488 {
00489 return Capability( Impl::buildHal( refers_r, name_r, op_r, edition_r.asString() ) );
00490 }
00491 if ( Impl::isModaliasSpec( name_r ) )
00492 {
00493 return Capability( Impl::buildModalias( refers_r, name_r, op_r, edition_r.asString() ) );
00494 }
00495 return Capability( Impl::buildVersioned( refers_r, name_r, op_r, edition_r ) );
00496 }
00497 catch ( Exception & excpt )
00498 {
00499 ZYPP_RETHROW( excpt );
00500 return Capability();
00501 }
00502
00504
00505
00506
00507
00508 Capability CapFactory::halEvalCap() const
00509 try
00510 {
00511 return Capability( Impl::buildHal( Resolvable::Kind(), "hal()" ) );
00512 }
00513 catch ( Exception & excpt )
00514 {
00515 ZYPP_RETHROW( excpt );
00516 return Capability();
00517 }
00518
00520
00521
00522
00523
00524 Capability CapFactory::modaliasEvalCap() const
00525 try
00526 {
00527 return Capability( Impl::buildModalias( Resolvable::Kind(), "modalias()" ) );
00528 }
00529 catch ( Exception & excpt )
00530 {
00531 ZYPP_RETHROW( excpt );
00532 return Capability();
00533 }
00534
00536
00537
00538
00539
00540 std::string CapFactory::encode( const Capability & cap_r ) const
00541 {
00542 return cap_r._pimpl->encode();
00543 }
00544
00545
00546
00547
00548
00549
00550 std::ostream & operator<<( std::ostream & str, const CapFactory & obj )
00551 {
00552 str << "CapFactory stats:" << endl;
00553
00554 return for_each( _uset.begin(), _uset.end(), USetStatsCollect() ).dumpOn( str );
00555 }
00556
00558 }