00001
00002
00003
00004
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
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
00048
00049
00050 impl->factoryCtor( media_r, context.path(), context.alias(), context.cacheDir(), context.baseSource(), context.autorefresh() );
00051 return impl;
00052 }
00053 };
00055
00057
00058
00059
00061
00063
00064
00065
00066
00067 SourceFactory::SourceFactory()
00068 {}
00069
00071
00072
00073
00074
00075 SourceFactory::~SourceFactory()
00076 {}
00077
00079
00080
00081
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
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
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
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
00210 media::MediaId id = media_mgr.open(url_r);
00211
00212
00213 media_mgr.addVerifier(id, media::MediaVerifierRef(new media::NoVerifier()));
00214
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
00237 }
00238 else if ( (probeYaST = probeSource<susetags::SuseTagsImpl>( url_r, path_r, id, "YaST", report )) )
00239 {
00240
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
00262
00263
00264 return Source_Ref();
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
00273
00274
00275
00276 #warning if cache_dir is provided, no need to open the original url
00277
00278 media::MediaId id = media_mgr.open(url_r);
00279
00280
00281 media_mgr.addVerifier(id, media::MediaVerifierRef(new media::NoVerifier()));
00282
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
00294 if ( auto_refresh == indeterminate )
00295 calculated_autorefresh = media::MediaAccess::canBeVolatile( url_r );
00296
00297
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
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();
00340 }
00341
00342
00343
00344
00345
00346
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;
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 }