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       // probeYUM
00230       try {
00231         probeYUM = probeSource<yum::YUMSourceImpl>( url_r, path_r, id, "YUM", report );
00232       }
00233       catch ( const media::MediaException & e ) {
00234         ZYPP_CAUGHT(e); // ignore while probing
00235       }
00236       if ( probeYUM )
00237       {
00238         report->finish(url_r, ProbeSourceReport::NO_ERROR, "");
00239         Source_Ref source(createSourceImplWorkflow<source::yum::YUMSourceImpl>( id, context ));
00240         return source;
00241       }
00242 
00243       // probeYaST
00244       try {
00245         probeYaST = probeSource<susetags::SuseTagsImpl>( url_r, path_r, id, "YaST", report );
00246       }
00247       catch ( const media::MediaException & e ) {
00248         ZYPP_CAUGHT(e); // ignore while probing
00249       }
00250       if ( probeYaST )
00251       {
00252         report->finish(url_r, ProbeSourceReport::NO_ERROR, "");
00253         Source_Ref source(createSourceImplWorkflow<susetags::SuseTagsImpl>( id, context ));
00254         return source;
00255       }
00256 
00257       // probing failed:
00258       report->finish(url_r, ProbeSourceReport::NO_ERROR, "");
00259       ZYPP_THROW( SourceUnknownTypeException("Unknown source type for " + url_r.asString() ) );
00260     }
00261     catch ( const Exception &e )
00262     {
00263       report->finish(url_r, ProbeSourceReport::IO, e.asUserString());
00264       ZYPP_RETHROW(e);
00265     }
00267     // TRY PLAINDIR
00269     //FIXME disabled
00270 
00271     return Source_Ref(); // not reached!!
00272   }
00273 
00274   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 )
00275   {
00276     if (! url_r.isValid())
00277       ZYPP_THROW( Exception("Empty URL passed to SourceFactory") );
00278 
00279     //callback::SendReport<CreateSourceReport> report;
00280 
00281     //report->startProbe (url_r);
00282 
00283 #warning if cache_dir is provided, no need to open the original url
00284     // open the media
00285     media::MediaId id = media_mgr.open(url_r);
00286 
00287     // add dummy verifier
00288     media_mgr.addVerifier(id, media::MediaVerifierRef(new media::NoVerifier()));
00289     // attach only if initializing from media and not from cache (#153073)
00290     if (cache_dir_r == "")
00291     {
00292       media_mgr.attach(id);
00293     }
00294     else
00295     {
00296       MIL << "Initializing from cache" << endl;
00297     }
00298 
00299     bool calculated_autorefresh = auto_refresh;
00300     // Sane default for unknown autorefresh
00301     if ( auto_refresh == indeterminate )
00302       calculated_autorefresh = media::MediaAccess::canBeVolatile( url_r );
00303 
00304     //SourceInfo( url, path, alias, cache_dir, autorefresh );
00305     SourceInfo context( url_r, path_r, alias_r, cache_dir_r, calculated_autorefresh );
00306     context.setBaseSource( base_source );
00307     context.setType( type );
00308 
00309     try
00310     {
00311       Source_Ref::Impl_Ptr impl;
00312 
00313       if( type == yum::YUMSourceImpl::typeString() )
00314       {
00315         MIL << "Trying the YUM source" << endl;
00316         impl = Source_Ref::Impl_Ptr( Impl::createSourceImpl<yum::YUMSourceImpl>(id, context ) );
00317         MIL << "YUM source created" << endl;
00318       }
00319       else if ( type == susetags::SuseTagsImpl::typeString() )
00320       {
00321         MIL << "Trying the SUSE tags source" << endl;
00322         impl = Source_Ref::Impl_Ptr( Impl::createSourceImpl<susetags::SuseTagsImpl>(id, context ) );
00323         MIL << "YaST source created" << endl;
00324       }
00325       else if ( type == PlaindirImpl::typeString() )
00326       {
00327         MIL << "Trying the Plaindir source" << endl;
00328         impl = Source_Ref::Impl_Ptr( Impl::createSourceImpl<PlaindirImpl>(id, context ) );
00329         MIL << "Plaindir source created" << endl;
00330       }
00331       else
00332       {
00333         ZYPP_THROW( Exception ("Cannot create source of unknown type '" + type + "'"));
00334       }
00335 
00336       // never reached
00337       return Source_Ref(impl);
00338     }
00339     catch (const Exception & excpt_r)
00340     {
00341       ZYPP_CAUGHT(excpt_r);
00342       MIL << "Creating a source of type " << type << " failed " << endl;
00343       ZYPP_RETHROW(excpt_r);
00344     }
00345 
00346     return Source_Ref(); // not reached!!
00347   }
00348 
00349 
00350   /******************************************************************
00351   **
00352   **    FUNCTION NAME : operator<<
00353   **    FUNCTION TYPE : std::ostream &
00354   */
00355   std::ostream & operator<<( std::ostream & str, const SourceFactory & obj )
00356   {
00357     return str << "SourceFactory";
00358   }
00359 
00360   void SourceFactory::scanProductsFile( const Pathname & file_r, ProductSet & pset_r ) const
00361   {
00362     std::ifstream pfile( file_r.asString().c_str() );
00363     while ( pfile.good() ) {
00364 
00365       std::string value = str::getline( pfile, str::TRIM );
00366       if ( pfile.bad() ) {
00367         ERR << "Error parsing " << file_r << endl;
00368         ZYPP_THROW(Exception("Error parsing " + file_r.asString()));
00369       }
00370       if ( pfile.fail() ) {
00371         break; // no data on last line
00372       }
00373       std::string tag = str::stripFirstWord( value, true );
00374 
00375       if ( tag.size() ) {
00376         pset_r.insert( ProductEntry( tag, value ) );
00377       }
00378     }
00379   }
00380 
00381 
00382 
00384 } // namespace zypp

Generated on Sat Sep 5 12:40:31 2009 for zypp by  doxygen 1.4.6