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     try
00137     {
00138       boost::function<bool()> probe = typename _SourceImpl::Prober( id, path_r );
00139 
00140       if ( probe() )
00141       {
00142         report->successProbe(url_r, type);
00143         return true;
00144       }
00145       else
00146       {
00147         report->failedProbe(url_r, type);
00148         return false;
00149       }
00150     }
00151     catch (const Exception & excpt_r)
00152     {
00153       report->finish(url_r, ProbeSourceReport::UNKNOWN, excpt_r.asUserString());
00154     }
00155     return false;
00156   }
00157 
00158   template<class _SourceImpl>
00159   Source_Ref SourceFactory::createSourceImplWorkflow( media::MediaId id, const SourceInfo &context )
00160   {
00161       //MIL << "Trying (pre) to create source of type " << _SourceImpl::typeString() << endl;
00162       callback::SendReport<SourceCreateReport> report;
00163       bool retry = true;
00164       while (retry)
00165       {
00166         report->start( context.url() );
00167           try
00168           {
00169             MIL << "Trying to create source of type " << _SourceImpl::typeString() << endl;
00170             Source_Ref::Impl_Ptr impl( Impl::createSourceImpl<_SourceImpl>( id, context ) );
00171             MIL << "Created source " << impl->type() << endl;
00172             report->finish( context.url(), SourceCreateReport::NO_ERROR, std::string() );
00173             return Source_Ref(impl);
00174           }
00175           catch (const SourceUserRejectedException & excpt_r)
00176           {
00177             ZYPP_CAUGHT(excpt_r);
00178             report->problem( context.url(), SourceCreateReport::REJECTED, "Source rejected by the user" );
00179             report->finish( context.url(), SourceCreateReport::NO_ERROR, "" );
00180             ZYPP_THROW(Exception( "Source Rejected: " + excpt_r.asUserString() ));
00181           }
00182           catch ( const SourceMetadataException & excpt_r )
00183           {
00184             ZYPP_CAUGHT(excpt_r);
00185             report->problem( context.url(), SourceCreateReport::REJECTED, "Source metadata is invalid: " + excpt_r.asUserString() );
00186             report->finish( context.url(), SourceCreateReport::REJECTED, ""  );
00187             ZYPP_THROW(Exception( "Invalid Source: " + excpt_r.asUserString() ));
00188           }
00189           catch (const Exception & excpt_r)
00190           {
00191             ZYPP_CAUGHT(excpt_r);
00192             if ( report->problem( context.url(), SourceCreateReport::UNKNOWN, "Unknown Error: " + excpt_r.asUserString() ) != SourceCreateReport::RETRY )
00193             {
00194               report->finish( context.url(), SourceCreateReport::UNKNOWN, std::string("Unknown Error: ") + excpt_r.asUserString() );
00195               ZYPP_THROW(Exception( "Unknown Error: " + excpt_r.asUserString() ));
00196             }
00197           }
00198       }
00199       // never reached
00200       return Source_Ref();
00201   }
00202 
00203   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 )
00204   {
00205     if (! url_r.isValid())
00206       ZYPP_THROW( Exception("Empty URL passed to SourceFactory") );
00207 
00208 #warning if cache_dir is provided, no need to open the original url
00209     // open the media
00210     media::MediaId id = media_mgr.open(url_r);
00211 
00212     // add dummy verifier
00213     media_mgr.addVerifier(id, media::MediaVerifierRef(new media::NoVerifier()));
00214     // attach only if initializing from media and not from cache (#153073)
00215     if (cache_dir_r == "")
00216     {
00217       media_mgr.attach(id);
00218     }
00219     else
00220     {
00221       MIL << "Initializing from cache" << endl;
00222     }
00223 
00224     bool auto_refresh = media::MediaAccess::canBeVolatile( url_r );
00225 
00226     SourceInfo context( url_r, path_r, alias_r, cache_dir_r, auto_refresh );
00227     context.setBaseSource( base_source );
00228 
00229     callback::SendReport<ProbeSourceReport> report;
00230     bool probeYUM = false;
00231     bool probeYaST = false;
00232 
00233     report->start(url_r);
00234     if ( (probeYUM = probeSource<yum::YUMSourceImpl>( url_r, path_r, id, "YUM", report )) )
00235     {
00236       // nothing
00237     }
00238     else if ( (probeYaST = probeSource<susetags::SuseTagsImpl>( url_r, path_r, id, "YaST", report )) )
00239     {
00240       // nohing
00241     }
00242     report->finish(url_r, ProbeSourceReport::NO_ERROR, "");
00243 
00244     if ( probeYUM )
00245     {
00246       Source_Ref source(createSourceImplWorkflow<source::yum::YUMSourceImpl>( id, context ));
00247       return source;
00248     }
00249     else if ( probeYaST )
00250     {
00251       Source_Ref source(createSourceImplWorkflow<susetags::SuseTagsImpl>( id, context ));
00252       return source;
00253     }
00254     else
00255     {
00256       ZYPP_THROW( SourceUnknownTypeException("Unknown source type for " + url_r.asString() ) );
00257     }
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 Tue Nov 28 16:49:33 2006 for zypp by  doxygen 1.5.0