SourceFactory.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #include <iostream>
00013 #include <fstream>
00014 #include "zypp/base/Logger.h"
00015 #include "zypp/base/Exception.h"
00016 #include "zypp/base/String.h"
00017 
00018 #include "zypp/SourceFactory.h"
00019 #include "zypp/source/Builtin.h"
00020 #include "zypp/media/MediaAccess.h"
00021 #include "zypp/ZYppCallbacks.h"
00022 
00023 using std::endl;
00024 using namespace zypp::source;
00025 
00027 namespace zypp
00028 { 
00029 
00030   media::MediaManager media_mgr;
00031 
00033   //
00034   //    CLASS NAME : SourceFactory::Impl
00035   //
00037   struct SourceFactory::Impl
00038   {
00042     template<class _SourceImpl>
00043       static Source_Ref::Impl_Ptr createSourceImpl( const media::MediaId & media_r,
00044                                                     const SourceInfo &context )
00045       {
00046         Source_Ref::Impl_Ptr impl( new _SourceImpl );
00047         // note, base_source is a tribool, if indeterminate we fallback to false
00048         //MIL << "Going to call factory ctor:" << endl;
00049         //MIL << context << endl;
00050         impl->factoryCtor( media_r, context.path(), context.alias(), context.cacheDir(), context.baseSource(), context.autorefresh() );
00051         return impl;
00052       }
00053   };
00055 
00057   //
00058   //    CLASS NAME : SourceFactory
00059   //
00061 
00063   //
00064   //    METHOD NAME : SourceFactory::SourceFactory
00065   //    METHOD TYPE : Ctor
00066   //
00067   SourceFactory::SourceFactory()
00068   {}
00069 
00071   //
00072   //    METHOD NAME : SourceFactory::~SourceFactory
00073   //    METHOD TYPE : Dtor
00074   //
00075   SourceFactory::~SourceFactory()
00076   {}
00077 
00079   //
00080   //    METHOD NAME : SourceFactory::createFrom
00081   //    METHOD TYPE : Source
00082   //
00083   Source_Ref SourceFactory::createFrom( const Source_Ref::Impl_Ptr & impl_r )
00084   {
00085     return impl_r ? Source_Ref( impl_r ) : Source_Ref::noSource;
00086   }
00087 
00088   void SourceFactory::listProducts( const Url & url_r, ProductSet & products_r )
00089   {
00090     if (! url_r.isValid())
00091       ZYPP_THROW( Exception("Empty URL passed to SourceFactory") );
00092 
00093     // open the media
00094     media::MediaId id = media_mgr.open(url_r);
00095     media_mgr.attach(id);
00096     Pathname products_file = Pathname("media.1/products");
00097 
00098     try  {
00099       media_mgr.provideFile (id, products_file);
00100       products_file = media_mgr.localPath (id, products_file);
00101       scanProductsFile (products_file, products_r);
00102     }
00103     catch ( const Exception & excpt ) {
00104       ZYPP_CAUGHT(excpt);
00105       MIL << "No products description found on the Url" << endl;
00106     }
00107 
00108     media_mgr.release(id);
00109   }
00110 
00111   Source_Ref SourceFactory::createFrom( const source::SourceInfo &context )
00112   {
00113     if ( context.type().empty() )
00114       {
00115         return createFrom( context.url(),
00116                            context.path(),
00117                            context.alias(),
00118                            context.cacheDir(),
00119                            context.baseSource() );
00120       }
00121     else
00122       {
00123         return createFrom( context.type(),
00124                            context.url(),
00125                            context.path(),
00126                            context.alias(),
00127                            context.cacheDir(),
00128                            context.baseSource(),
00129                            context.autorefresh() );
00130       }
00131   }
00132 
00133   template<typename _SourceImpl>
00134   static bool probeSource(const Url &url_r, const Pathname &path_r, media::MediaId id, const std::string &type, callback::SendReport<ProbeSourceReport> &report )
00135   {
00136       boost::function<bool()> probe = typename _SourceImpl::Prober( id, path_r );
00137 
00138       if ( probe() )
00139       {
00140         report->successProbe(url_r, type);
00141         return true;
00142       }
00143       else
00144       {
00145         report->failedProbe(url_r, type);
00146         return false;
00147       }
00148     return false;
00149   }
00150 
00151   template<class _SourceImpl>
00152   Source_Ref SourceFactory::createSourceImplWorkflow( media::MediaId id, const SourceInfo &context )
00153   {
00154       //MIL << "Trying (pre) to create source of type " << _SourceImpl::typeString() << endl;
00155       callback::SendReport<SourceCreateReport> report;
00156       bool retry = true;
00157       while (retry)
00158       {
00159         report->start( context.url() );
00160           try
00161           {
00162             MIL << "Trying to create source of type " << _SourceImpl::typeString() << endl;
00163             Source_Ref::Impl_Ptr impl( Impl::createSourceImpl<_SourceImpl>( id, context ) );
00164             MIL << "Created source " << impl->type() << endl;
00165             report->finish( context.url(), SourceCreateReport::NO_ERROR, std::string() );
00166             return Source_Ref(impl);
00167           }
00168           catch (const SourceUserRejectedException & excpt_r)
00169           {
00170             ZYPP_CAUGHT(excpt_r);
00171             report->problem( context.url(), SourceCreateReport::REJECTED, "Source rejected by the user" );
00172             report->finish( context.url(), SourceCreateReport::NO_ERROR, "" );
00173             ZYPP_THROW(Exception( "Source Rejected: " + excpt_r.asUserString() ));
00174           }
00175           catch ( const SourceMetadataException & excpt_r )
00176           {
00177             ZYPP_CAUGHT(excpt_r);
00178             report->problem( context.url(), SourceCreateReport::REJECTED, "Source metadata is invalid: " + excpt_r.asUserString() );
00179             report->finish( context.url(), SourceCreateReport::REJECTED, ""  );
00180             ZYPP_THROW(Exception( "Invalid Source: " + excpt_r.asUserString() ));
00181           }
00182           catch (const Exception & excpt_r)
00183           {
00184             ZYPP_CAUGHT(excpt_r);
00185             if ( report->problem( context.url(), SourceCreateReport::UNKNOWN, "Unknown Error: " + excpt_r.asUserString() ) != SourceCreateReport::RETRY )
00186             {
00187               report->finish( context.url(), SourceCreateReport::UNKNOWN, std::string("Unknown Error: ") + excpt_r.asUserString() );
00188               ZYPP_THROW(Exception( "Unknown Error: " + excpt_r.asUserString() ));
00189             }
00190           }
00191       }
00192       // never reached
00193       return Source_Ref();
00194   }
00195 
00196   Source_Ref SourceFactory::createFrom( const Url & url_r, const Pathname & path_r, const std::string & alias_r, const Pathname & cache_dir_r, bool base_source )
00197   {
00198     if (! url_r.isValid())
00199       ZYPP_THROW( Exception("Empty URL passed to SourceFactory") );
00200 
00201 #warning if cache_dir is provided, no need to open the original url
00202     // open the media
00203     media::MediaId id = media_mgr.open(url_r);
00204 
00205     // add dummy verifier
00206     media_mgr.addVerifier(id, media::MediaVerifierRef(new media::NoVerifier()));
00207     // attach only if initializing from media and not from cache (#153073)
00208     if (cache_dir_r == "")
00209     {
00210       media_mgr.attach(id);
00211     }
00212     else
00213     {
00214       MIL << "Initializing from cache" << endl;
00215     }
00216 
00217     bool auto_refresh = media::MediaAccess::canBeVolatile( url_r );
00218 
00219     SourceInfo context( url_r, path_r, alias_r, cache_dir_r, auto_refresh );
00220     context.setBaseSource( base_source );
00221 
00222     callback::SendReport<ProbeSourceReport> report;
00223     bool probeYUM = false;
00224     bool probeYaST = false;
00225 
00226     report->start(url_r);
00227     try
00228     {
00229       if ( (probeYUM = probeSource<yum::YUMSourceImpl>( url_r, path_r, id, "YUM", report )) )
00230       {
00231         // nothing
00232       }
00233       else if ( (probeYaST = probeSource<susetags::SuseTagsImpl>( url_r, path_r, id, "YaST", report )) )
00234       {
00235         // nohing
00236       }
00237       report->finish(url_r, ProbeSourceReport::NO_ERROR, "");
00238   
00239       if ( probeYUM )
00240       {
00241         Source_Ref source(createSourceImplWorkflow<source::yum::YUMSourceImpl>( id, context ));
00242         return source;
00243       }
00244       else if ( probeYaST )
00245       {
00246         Source_Ref source(createSourceImplWorkflow<susetags::SuseTagsImpl>( id, context ));
00247         return source;
00248       }
00249       else
00250       {
00251         ZYPP_THROW( SourceUnknownTypeException("Unknown source type for " + url_r.asString() ) );
00252       }
00253     }
00254     catch ( const Exception &e )
00255     {
00256       report->finish(url_r, ProbeSourceReport::IO, e.asUserString());
00257       ZYPP_RETHROW(e);
00258     }
00260     // TRY PLAINDIR
00262     //FIXME disabled
00263 
00264     return Source_Ref(); // not reached!!
00265   }
00266 
00267   Source_Ref SourceFactory::createFrom( const std::string & type, const Url & url_r, const Pathname & path_r, const std::string & alias_r, const Pathname & cache_dir_r, bool base_source, tribool auto_refresh )
00268   {
00269     if (! url_r.isValid())
00270       ZYPP_THROW( Exception("Empty URL passed to SourceFactory") );
00271 
00272     //callback::SendReport<CreateSourceReport> report;
00273 
00274     //report->startProbe (url_r);
00275 
00276 #warning if cache_dir is provided, no need to open the original url
00277     // open the media
00278     media::MediaId id = media_mgr.open(url_r);
00279 
00280     // add dummy verifier
00281     media_mgr.addVerifier(id, media::MediaVerifierRef(new media::NoVerifier()));
00282     // attach only if initializing from media and not from cache (#153073)
00283     if (cache_dir_r == "")
00284     {
00285       media_mgr.attach(id);
00286     }
00287     else
00288     {
00289       MIL << "Initializing from cache" << endl;
00290     }
00291 
00292     bool calculated_autorefresh = auto_refresh;
00293     // Sane default for unknown autorefresh
00294     if ( auto_refresh == indeterminate )
00295       calculated_autorefresh = media::MediaAccess::canBeVolatile( url_r );
00296 
00297     //SourceInfo( url, path, alias, cache_dir, autorefresh );
00298     SourceInfo context( url_r, path_r, alias_r, cache_dir_r, calculated_autorefresh );
00299     context.setBaseSource( base_source );
00300     context.setType( type );
00301 
00302     try
00303     {
00304       Source_Ref::Impl_Ptr impl;
00305 
00306       if( type == yum::YUMSourceImpl::typeString() )
00307       {
00308         MIL << "Trying the YUM source" << endl;
00309         impl = Source_Ref::Impl_Ptr( Impl::createSourceImpl<yum::YUMSourceImpl>(id, context ) );
00310         MIL << "YUM source created" << endl;
00311       }
00312       else if ( type == susetags::SuseTagsImpl::typeString() )
00313       {
00314         MIL << "Trying the SUSE tags source" << endl;
00315         impl = Source_Ref::Impl_Ptr( Impl::createSourceImpl<susetags::SuseTagsImpl>(id, context ) );
00316         MIL << "YaST source created" << endl;
00317       }
00318       else if ( type == PlaindirImpl::typeString() )
00319       {
00320         MIL << "Trying the Plaindir source" << endl;
00321         impl = Source_Ref::Impl_Ptr( Impl::createSourceImpl<PlaindirImpl>(id, context ) );
00322         MIL << "Plaindir source created" << endl;
00323       }
00324       else
00325       {
00326         ZYPP_THROW( Exception ("Cannot create source of unknown type '" + type + "'"));
00327       }
00328 
00329       // never reached
00330       return Source_Ref(impl);
00331     }
00332     catch (const Exception & excpt_r)
00333     {
00334       ZYPP_CAUGHT(excpt_r);
00335       MIL << "Creating a source of type " << type << " failed " << endl;
00336       ZYPP_RETHROW(excpt_r);
00337     }
00338 
00339     return Source_Ref(); // not reached!!
00340   }
00341 
00342 
00343   /******************************************************************
00344   **
00345   **    FUNCTION NAME : operator<<
00346   **    FUNCTION TYPE : std::ostream &
00347   */
00348   std::ostream & operator<<( std::ostream & str, const SourceFactory & obj )
00349   {
00350     return str << "SourceFactory";
00351   }
00352 
00353   void SourceFactory::scanProductsFile( const Pathname & file_r, ProductSet & pset_r ) const
00354   {
00355     std::ifstream pfile( file_r.asString().c_str() );
00356     while ( pfile.good() ) {
00357 
00358       std::string value = str::getline( pfile, str::TRIM );
00359       if ( pfile.bad() ) {
00360         ERR << "Error parsing " << file_r << endl;
00361         ZYPP_THROW(Exception("Error parsing " + file_r.asString()));
00362       }
00363       if ( pfile.fail() ) {
00364         break; // no data on last line
00365       }
00366       std::string tag = str::stripFirstWord( value, true );
00367 
00368       if ( tag.size() ) {
00369         pset_r.insert( ProductEntry( tag, value ) );
00370       }
00371     }
00372   }
00373 
00374 
00375 
00377 } // namespace zypp

Generated on Thu Apr 24 02:24:58 2008 for zypp by  doxygen 1.4.6