CapabilityImpl.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #include <iostream>
00013 
00014 #include "zypp/base/Logger.h"
00015 #include "zypp/base/Regex.h"
00016 #include "zypp/base/Exception.h"
00017 #include "zypp/capability/CapabilityImpl.h"
00018 #include "zypp/capability/Capabilities.h"
00019 
00020 using namespace std;
00021 
00023 namespace zypp
00024 { 
00025 
00026   namespace capability
00027   { 
00028     IMPL_PTR_TYPE(CapabilityImpl)
00029 
00030     
00031     //
00032     //  METHOD NAME : CapabilityImpl::CapabilityImpl
00033     //  METHOD TYPE : Ctor
00034     //
00035     CapabilityImpl::CapabilityImpl( const Resolvable::Kind & refers_r )
00036     : _refers( refers_r )
00037     {}
00038 
00040     //
00041     //  METHOD NAME : CapabilityImpl::capImplOrderLess
00042     //  METHOD TYPE : bool
00043     //
00044     bool CapabilityImpl::capImplOrderLess( const constPtr & rhs ) const
00045     {
00046       return encode() < rhs->encode();
00047     }
00048 
00050     //
00051     //  METHOD NAME : CapabilityImpl::capImplOrderLess
00052     //  METHOD TYPE : bool
00053     //
00054     std::ostream & CapabilityImpl::dumpOn( std::ostream & str ) const
00055     {
00056       return str << '[' << refers() << "] "
00057                  << '(' << kind() << ") "
00058                  << asString();
00059     }
00060 
00062     static void assertResKind( const Resolvable::Kind & refers_r )
00063     {
00064       if ( refers_r == Resolvable::Kind() )
00065         ZYPP_THROW( Exception("Missing or empty  Resolvable::Kind in Capability") );
00066     }
00067 
00068     bool isEditionSpec( Rel op_r, const Edition & edition_r )
00069     {
00070       switch ( op_r.inSwitch() )
00071         {
00072         case Rel::ANY_e:
00073           if ( edition_r != Edition::noedition )
00074             WAR << "Operator " << op_r << " causes Edition "
00075             << edition_r << " to be ignored." << endl;
00076           return false;
00077           break;
00078 
00079         case Rel::NONE_e:
00080           ZYPP_THROW( Exception("Operator NONE is not allowed in Capability") );
00081           break;
00082 
00083         case Rel::EQ_e:
00084         case Rel::NE_e:
00085         case Rel::LT_e:
00086         case Rel::LE_e:
00087         case Rel::GT_e:
00088         case Rel::GE_e:
00089           return true;
00090           break;
00091         }
00092       // SHOULD NOT GET HERE
00093       ZYPP_THROW( Exception("Unknown Operator NONE is not allowed in Capability") );
00094       return false; // not reached
00095     }
00096 
00097     bool isFileSpec( const std::string & name_r )
00098     {
00099       return *name_r.c_str() == '/';
00100     }
00101 
00102     bool isInterestingFileSpec( const std::string & name_r )
00103     {
00104       static str::smatch what;
00105       static const str::regex filenameRegex(
00106           "/(s?bin|lib(64)?|etc)/|^/usr/(games/|share/(dict/words|magic\\.mime)$)|^/opt/gnome/games/",
00107           str::regex::optimize|str::regex::nosubs );
00108 
00109       return str::regex_match( name_r, what, filenameRegex );
00110     }
00111 
00112     bool isSplitSpec( const std::string & name_r )
00113     {
00114       return name_r.find( ":/" ) != std::string::npos;
00115     }
00116 
00117     bool isHalSpec( const std::string & name_r )
00118     {
00119       return name_r.substr(0,4) == "hal(";
00120     }
00121 
00122     bool isModaliasSpec( const std::string & name_r )
00123     {
00124       return name_r.substr(0,9) == "modalias(";
00125     }
00126 
00127     bool isFilesystemSpec( const std::string & name_r )
00128     {
00129       return name_r.substr(0,11) == "filesystem(";
00130     }
00131 
00132     CapabilityImpl::Ptr buildFile( const Resolvable::Kind & refers_r,
00133                                           const std::string & name_r )
00134     {
00135       // NullCap check first:
00136       if ( name_r.empty() )
00137         {
00138           // Singleton, so no need to put it into _uset !?
00139           return capability::NullCap::instance();
00140         }
00141 
00142       assertResKind( refers_r );
00143 
00144       return new capability::FileCap( refers_r, name_r );
00145     }
00146 
00147     CapabilityImpl::Ptr buildNamed( const Resolvable::Kind & refers_r,
00148                                            const std::string & name_r )
00149     {
00150       // NullCap check first:
00151       if ( name_r.empty() )
00152       {
00153         // Singleton, so no need to put it into _uset !?
00154         return capability::NullCap::instance();
00155       }
00156 
00157       assertResKind( refers_r );
00158 
00159       // file:    /absolute/path
00160       if ( isFileSpec( name_r ) )
00161       {
00162         return new capability::FileCap( refers_r, name_r );
00163       }
00164       if ( isFilesystemSpec( name_r ) )
00165       {
00166         return buildFilesystem( refers_r, name_r );
00167       }
00168 
00169       //split:   name:/absolute/path
00170       static const str::regex  rx( "([^/]*):(/.*)" );
00171       str::smatch what;
00172       if( str::regex_match( name_r, what, rx ) )
00173       {
00174         return new capability::SplitCap( refers_r, what[1], what[2] );
00175       }
00176 
00177       //name:    name
00178       return new capability::NamedCap( refers_r, name_r );
00179     }
00180 
00181     CapabilityImpl::Ptr buildVersioned( const Resolvable::Kind & refers_r,
00182                                                const std::string & name_r,
00183                                                Rel op_r,
00184                                                const Edition & edition_r )
00185     {
00186       if ( isEditionSpec( op_r, edition_r ) )
00187         {
00188           assertResKind( refers_r );
00189 
00190           // build a VersionedCap
00191           return new capability::VersionedCap( refers_r, name_r, op_r, edition_r );
00192         }
00193       //else
00194       // build a NamedCap
00195 
00196       return buildNamed( refers_r, name_r );
00197     }
00198 
00199     CapabilityImpl::Ptr buildHal( const Resolvable::Kind & refers_r,
00200                                          const std::string & name_r,
00201                                          Rel op_r,
00202                                          const std::string & value_r )
00203     {
00204       if ( op_r != Rel::ANY )
00205         {
00206           ZYPP_THROW( Exception("Unsupported kind of Hal Capability '" + op_r.asString() + "'") );
00207         }
00208 
00209       //split:   hal(name) [op string]
00210       static const str::regex  rx( "hal\\(([^)]*)\\)" );
00211       str::smatch what;
00212       if( str::regex_match( name_r, what, rx ) )
00213         {
00214           // Hal always refers to 'System' kind of Resolvable.
00215           return new capability::HalCap( ResTraits<SystemResObject>::kind,
00216                                     what[1] );
00217         }
00218       // otherwise
00219       ZYPP_THROW( Exception("Unsupported kind of Hal Capability '" + name_r + "'") );
00220       return NULL; // make gcc happy
00221     }
00222 
00223     CapabilityImpl::Ptr buildModalias( const Resolvable::Kind & refers_r,
00224                                               const std::string & name_r,
00225                                               Rel op_r,
00226                                               const std::string & value_r )
00227     {
00228       if ( op_r != Rel::ANY )
00229         {
00230           ZYPP_THROW( Exception("Unsupported kind of Modalias Capability  '" + op_r.asString() + "'") );
00231         }
00232 
00233       //split:   modalias(name) [op string]
00234       static const str::regex  rx( "modalias\\(([^)]*)\\)" );
00235       str::smatch what;
00236       if( str::regex_match( name_r, what, rx ) )
00237         {
00238           // Modalias always refers to 'System' kind of Resolvable
00239           return new capability::ModaliasCap( ResTraits<SystemResObject>::kind,
00240                                          what[1] );
00241         }
00242       // otherwise
00243       ZYPP_THROW( Exception("Unsupported kind of Modalias Capability'" + name_r + "'") );
00244       return NULL; // make gcc happy
00245     }
00246 
00247     /******************************************************************
00248     **
00249     **  FUNCTION NAME : buildFilesystem
00250     **  FUNCTION TYPE : CapabilityImpl::Ptr
00251     */
00252     CapabilityImpl::Ptr buildFilesystem( const Resolvable::Kind & refers_r,
00253                                        const std::string & name_r )
00254     {
00255       //split:   filesystem(name) [op string]
00256       static const str::regex  rx( "filesystem\\(([^)]*)\\)" );
00257       str::smatch what;
00258       if( str::regex_match( name_r, what, rx ) )
00259       {
00260         // Filesystem always refers to 'System' kind of Resolvable
00261         return new capability::FilesystemCap( ResTraits<SystemResObject>::kind,
00262                                               what[1] );
00263       }
00264       // otherwise
00265       ZYPP_THROW( Exception("Unsupported kind of Filesystem Capability'" + name_r + "'") );
00266       return NULL; // make gcc happy
00267     }
00268 
00269 
00270     CapabilityImpl::Ptr parse( const Resolvable::Kind & refers_r,
00271                                const std::string & strval_r )
00272   try
00273     {
00274       if ( isHalSpec( strval_r ) )
00275         {
00276           return buildHal( refers_r, strval_r );
00277         }
00278       if ( isModaliasSpec( strval_r ) )
00279         {
00280           return buildModalias( refers_r, strval_r );
00281         }
00282       if ( isFilesystemSpec( strval_r ) )
00283         {
00284           return buildFilesystem( refers_r, strval_r );
00285         }
00286       if ( isFileSpec( strval_r ) )
00287         {
00288           return buildFile( refers_r, strval_r );
00289         }
00290 
00291       // strval_r has at least two words which could make 'op edition'?
00292       // improve regex!
00293       static const str::regex  rx( "(.*[^ \t])([ \t]+)([^ \t]+)([ \t]+)([^ \t]+)" );
00294       str::smatch what;
00295       if( str::regex_match( strval_r,what, rx ) )
00296         {
00297           Rel op;
00298           Edition edition;
00299           try
00300             {
00301               op = Rel(what[3]);
00302               edition = Edition(what[5]);
00303             }
00304           catch ( Exception & excpt )
00305             {
00306               // So they don't make valid 'op edition'
00307               ZYPP_CAUGHT( excpt );
00308               DBG << "Trying named cap for: " << strval_r << endl;
00309               // See whether it makes a named cap.
00310               return buildNamed( refers_r, strval_r );
00311             }
00312 
00313           // Valid 'op edition'
00314           return buildVersioned( refers_r,
00315                                  what[1], op, edition );
00316         }
00317       //else
00318       // not a VersionedCap
00319       return buildNamed( refers_r, strval_r );
00320     }
00321   catch ( Exception & excpt )
00322     {
00323       ZYPP_RETHROW( excpt );
00324       return NULL; // not reached
00325     }
00326 
00327 
00328   CapabilityImpl::Ptr parse( const Resolvable::Kind & refers_r,
00329                                 const std::string & name_r,
00330                                 const std::string & op_r,
00331                                 const std::string & edition_r )
00332     try
00333     {
00334       if ( isHalSpec( name_r ) )
00335       {
00336         return buildHal( refers_r, name_r, Rel(op_r), edition_r );
00337       }
00338       if ( isModaliasSpec( name_r ) )
00339         {
00340           return buildModalias( refers_r, name_r, Rel(op_r), edition_r );
00341         }
00342       // Try creating Rel and Edition, then parse
00343       return parse( refers_r, name_r, Rel(op_r), Edition(edition_r) );
00344     }
00345     catch ( Exception & excpt )
00346     {
00347       ZYPP_RETHROW( excpt );
00348       return NULL; // not reached
00349     }
00350 
00352   //
00353   //    METHOD NAME : CapFactory::parse
00354   //    METHOD TYPE : Capability
00355   //
00356   CapabilityImpl::Ptr parse( const Resolvable::Kind & refers_r,
00357                              const std::string & name_r,
00358                              Rel op_r,
00359                              const Edition & edition_r )
00360   try
00361   {
00362       if ( isHalSpec( name_r ) )
00363       {
00364         return buildHal( refers_r, name_r, op_r, edition_r.asString() );
00365       }
00366       if ( isModaliasSpec( name_r ) )
00367       {
00368         return buildModalias( refers_r, name_r, op_r, edition_r.asString() );
00369       }
00370       return buildVersioned( refers_r, name_r, op_r, edition_r );
00371   }
00372   catch ( Exception & excpt )
00373   {
00374       ZYPP_RETHROW( excpt );
00375       return NULL; // not reached
00376   }
00377 
00379 
00381   } // namespace capability
00384 } // namespace zypp

Generated on Tue Sep 25 19:23:00 2007 for libzypp by  doxygen 1.5.3