00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013 #include <functional>
00014 #include <set>
00015 #include <map>
00016
00017 #include "zypp/base/Logger.h"
00018 #include "zypp/base/Exception.h"
00019 #include "zypp/base/String.h"
00020 #include "zypp/base/Counter.h"
00021
00022 #include "zypp/CapFactory.h"
00023 #include "zypp/capability/Capabilities.h"
00024
00025 using std::endl;
00026
00028 namespace
00029 {
00030 using ::zypp::Resolvable;
00031 using ::zypp::capability::CapabilityImpl;
00032 using ::zypp::capability::CapImplOrder;
00033
00035 typedef std::set<CapabilityImpl::Ptr,CapImplOrder> USet;
00036
00043 USet _uset;
00044
00054 CapabilityImpl::Ptr usetInsert( CapabilityImpl * allocated_r )
00055 {
00056 return *(_uset.insert( CapabilityImpl::Ptr(allocated_r) ).first);
00057 }
00058
00062 struct USetStatsCollect : public std::unary_function<CapabilityImpl::constPtr, void>
00063 {
00064 typedef ::zypp::Counter<unsigned> Counter;
00065
00066 Counter _caps;
00067 std::map<CapabilityImpl::Kind,Counter> _capKind;
00068 std::map<Resolvable::Kind,Counter> _capRefers;
00069
00070 void operator()( const CapabilityImpl::constPtr & cap_r )
00071 {
00072
00073 ++_caps;
00074 ++(_capKind[cap_r->kind()]);
00075 ++(_capRefers[cap_r->refers()]);
00076 }
00077
00078 std::ostream & dumpOn( std::ostream & str ) const
00079 {
00080 str << " Capabilities total: " << _caps << endl;
00081 str << " Capability kinds:" << endl;
00082 for ( std::map<CapabilityImpl::Kind,Counter>::const_iterator it = _capKind.begin();
00083 it != _capKind.end(); ++it )
00084 {
00085 str << " " << it->first << '\t' << it->second << endl;
00086 }
00087 str << " Capability refers:" << endl;
00088 for ( std::map<Resolvable::Kind,Counter>::const_iterator it = _capRefers.begin();
00089 it != _capRefers.end(); ++it )
00090 {
00091 str << " " << it->first << '\t' << it->second << endl;
00092 }
00093 return str;
00094 }
00095 };
00096
00098 }
00100
00102 namespace zypp
00103 {
00104
00106
00107
00108
00126 struct CapFactory::Impl
00127 {
00129 static void assertResKind( const Resolvable::Kind & refers_r )
00130 {
00131 if ( refers_r == Resolvable::Kind() )
00132 ZYPP_THROW( Exception("Missing or empty Resolvable::Kind in Capability") );
00133 }
00134
00144 static bool isEditionSpec( Rel op_r, const Edition & edition_r )
00145 {
00146 switch ( op_r.inSwitch() )
00147 {
00148 case Rel::ANY_e:
00149 if ( edition_r != Edition::noedition )
00150 WAR << "Operator " << op_r << " causes Edition "
00151 << edition_r << " to be ignored." << endl;
00152 return false;
00153 break;
00154
00155 case Rel::NONE_e:
00156 ZYPP_THROW( Exception("Operator NONE is not allowed in Capability") );
00157 break;
00158
00159 case Rel::EQ_e:
00160 case Rel::NE_e:
00161 case Rel::LT_e:
00162 case Rel::LE_e:
00163 case Rel::GT_e:
00164 case Rel::GE_e:
00165 return true;
00166 break;
00167 }
00168
00169 ZYPP_THROW( Exception("Unknow Operator NONE is not allowed in Capability") );
00170 return false;
00171 }
00172
00174 static bool isFileSpec( const std::string & name_r )
00175 {
00176 return *name_r.c_str() == '/';
00177 }
00178
00180 static bool isSplitSpec( const std::string & name_r )
00181 {
00182 return name_r.find( ":/" ) != std::string::npos;
00183 }
00184
00186 static bool isHalSpec( const std::string & name_r )
00187 {
00188 return name_r.substr(0,4) == "hal(";
00189 }
00190
00192 static bool isModaliasSpec( const std::string & name_r )
00193 {
00194 return name_r.substr(0,9) == "modalias(";
00195 }
00196
00197 static CapabilityImpl::Ptr buildFile( const Resolvable::Kind & refers_r,
00198 const std::string & name_r )
00199 {
00200
00201 if ( name_r.empty() )
00202 {
00203
00204 return capability::NullCap::instance();
00205 }
00206
00207 assertResKind( refers_r );
00208
00209 return usetInsert
00210 ( new capability::FileCap( refers_r, name_r ) );
00211 }
00212
00219 static CapabilityImpl::Ptr buildNamed( const Resolvable::Kind & refers_r,
00220 const std::string & name_r )
00221 {
00222
00223 if ( name_r.empty() )
00224 {
00225
00226 return capability::NullCap::instance();
00227 }
00228
00229 assertResKind( refers_r );
00230
00231
00232 if ( isFileSpec( name_r ) )
00233 return usetInsert
00234 ( new capability::FileCap( refers_r, name_r ) );
00235
00236
00237 static const str::regex rx( "([^/]*):(/.*)" );
00238 str::smatch what;
00239 if( str::regex_match( name_r.begin(), name_r.end(), what, rx ) )
00240 {
00241 return usetInsert
00242 ( new capability::SplitCap( refers_r, what[1].str(), what[2].str() ) );
00243 }
00244
00245
00246 return usetInsert
00247 ( new capability::NamedCap( refers_r, name_r ) );
00248 }
00249
00258 static CapabilityImpl::Ptr buildVersioned( const Resolvable::Kind & refers_r,
00259 const std::string & name_r,
00260 Rel op_r,
00261 const Edition & edition_r )
00262 {
00263 if ( Impl::isEditionSpec( op_r, edition_r ) )
00264 {
00265 assertResKind( refers_r );
00266
00267
00268 return usetInsert
00269 ( new capability::VersionedCap( refers_r, name_r, op_r, edition_r ) );
00270 }
00271
00272
00273
00274 return buildNamed( refers_r, name_r );
00275 }
00276
00285 static CapabilityImpl::Ptr buildHal( const Resolvable::Kind & refers_r,
00286 const std::string & name_r,
00287 Rel op_r = Rel::ANY,
00288 const std::string & value_r = std::string() )
00289 {
00290 if ( op_r != Rel::ANY )
00291 {
00292 ZYPP_THROW( Exception("Unsupported kind of Hal Capability '" + op_r.asString() + "'") );
00293 }
00294
00295
00296 static const str::regex rx( "hal\\(([^)]*)\\)" );
00297 str::smatch what;
00298 if( str::regex_match( name_r.begin(), name_r.end(), what, rx ) )
00299 {
00300
00301 return usetInsert
00302 ( new capability::HalCap( ResTraits<SystemResObject>::kind,
00303 what[1].str() ) );
00304 }
00305
00306 ZYPP_THROW( Exception("Unsupported kind of Hal Capability '" + name_r + "'") );
00307 return NULL;
00308 }
00309
00310
00319 static CapabilityImpl::Ptr buildModalias( const Resolvable::Kind & refers_r,
00320 const std::string & name_r,
00321 Rel op_r = Rel::ANY,
00322 const std::string & value_r = std::string() )
00323 {
00324 if ( op_r != Rel::ANY )
00325 {
00326 ZYPP_THROW( Exception("Unsupported kind of Modalias Capability '" + op_r.asString() + "'") );
00327 }
00328
00329
00330 static const str::regex rx( "modalias\\(([^)]*)\\)" );
00331 str::smatch what;
00332 if( str::regex_match( name_r.begin(), name_r.end(), what, rx ) )
00333 {
00334
00335 return usetInsert
00336 ( new capability::ModaliasCap( ResTraits<SystemResObject>::kind,
00337 what[1].str() ) );
00338 }
00339
00340 ZYPP_THROW( Exception("Unsupported kind of Modalias Capability'" + name_r + "'") );
00341 return NULL;
00342 }
00343 };
00345
00347
00349
00350
00351
00353
00355
00356
00357
00358
00359 CapFactory::CapFactory()
00360 {}
00361
00363
00364
00365
00366
00367 CapFactory::~CapFactory()
00368 {}
00369
00371
00372
00373
00374
00375 Capability CapFactory::parse( const Resolvable::Kind & refers_r,
00376 const std::string & strval_r ) const
00377
00378 try
00379 {
00380 if ( Impl::isHalSpec( strval_r ) )
00381 {
00382 return Capability( Impl::buildHal( refers_r, strval_r ) );
00383 }
00384 if ( Impl::isModaliasSpec( strval_r ) )
00385 {
00386 return Capability( Impl::buildModalias( refers_r, strval_r ) );
00387 }
00388 if ( Impl::isFileSpec( strval_r ) )
00389 {
00390 return Capability( Impl::buildFile( refers_r, strval_r ) );
00391 }
00392
00393
00394
00395 static const str::regex rx( "(.*[^ \t])([ \t]+)([^ \t]+)([ \t]+)([^ \t]+)" );
00396 str::smatch what;
00397 if( str::regex_match( strval_r.begin(), strval_r.end(),what, rx ) )
00398 {
00399 Rel op;
00400 Edition edition;
00401 try
00402 {
00403 op = Rel(what[3].str());
00404 edition = Edition(what[5].str());
00405 }
00406 catch ( Exception & excpt )
00407 {
00408
00409 ZYPP_CAUGHT( excpt );
00410 DBG << "Trying named cap for: " << strval_r << endl;
00411
00412 return Capability( Impl::buildNamed( refers_r, strval_r ) );
00413 }
00414
00415
00416 return Capability ( Impl::buildVersioned( refers_r,
00417 what[1].str(), op, edition ) );
00418 }
00419
00420
00421 return Capability( Impl::buildNamed( refers_r, strval_r ) );
00422 }
00423 catch ( Exception & excpt )
00424 {
00425 ZYPP_RETHROW( excpt );
00426 return Capability();
00427 }
00428
00429
00431
00432
00433
00434
00435 Capability CapFactory::parse( const Resolvable::Kind & refers_r,
00436 const std::string & name_r,
00437 const std::string & op_r,
00438 const std::string & edition_r ) const
00439 try
00440 {
00441 if ( Impl::isHalSpec( name_r ) )
00442 {
00443 return Capability( Impl::buildHal( refers_r, name_r, Rel(op_r), edition_r ) );
00444 }
00445 if ( Impl::isModaliasSpec( name_r ) )
00446 {
00447 return Capability( Impl::buildModalias( refers_r, name_r, Rel(op_r), edition_r ) );
00448 }
00449
00450 return parse( refers_r, name_r, Rel(op_r), Edition(edition_r) );
00451 }
00452 catch ( Exception & excpt )
00453 {
00454 ZYPP_RETHROW( excpt );
00455 return Capability();
00456 }
00457
00459
00460
00461
00462
00463 Capability CapFactory::parse( const Resolvable::Kind & refers_r,
00464 const std::string & name_r,
00465 Rel op_r,
00466 const Edition & edition_r ) const
00467 try
00468 {
00469 if ( Impl::isHalSpec( name_r ) )
00470 {
00471 return Capability( Impl::buildHal( refers_r, name_r, op_r, edition_r.asString() ) );
00472 }
00473 if ( Impl::isModaliasSpec( name_r ) )
00474 {
00475 return Capability( Impl::buildModalias( refers_r, name_r, op_r, edition_r.asString() ) );
00476 }
00477 return Capability( Impl::buildVersioned( refers_r, name_r, op_r, edition_r ) );
00478 }
00479 catch ( Exception & excpt )
00480 {
00481 ZYPP_RETHROW( excpt );
00482 return Capability();
00483 }
00484
00486
00487
00488
00489
00490 Capability CapFactory::halEvalCap() const
00491 try
00492 {
00493 return Capability( Impl::buildHal( Resolvable::Kind(), "hal()" ) );
00494 }
00495 catch ( Exception & excpt )
00496 {
00497 ZYPP_RETHROW( excpt );
00498 return Capability();
00499 }
00500
00502
00503
00504
00505
00506 Capability CapFactory::modaliasEvalCap() const
00507 try
00508 {
00509 return Capability( Impl::buildModalias( Resolvable::Kind(), "modalias()" ) );
00510 }
00511 catch ( Exception & excpt )
00512 {
00513 ZYPP_RETHROW( excpt );
00514 return Capability();
00515 }
00516
00518
00519
00520
00521
00522 std::string CapFactory::encode( const Capability & cap_r ) const
00523 {
00524 return cap_r._pimpl->encode();
00525 }
00526
00527
00528
00529
00530
00531
00532 std::ostream & operator<<( std::ostream & str, const CapFactory & obj )
00533 {
00534 str << "CapFactory stats:" << endl;
00535
00536 return for_each( _uset.begin(), _uset.end(), USetStatsCollect() ).dumpOn( str );
00537 }
00538
00540 }