1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/SourceFactory.cc
14 #include "zypp/base/Logger.h"
15 #include "zypp/base/Exception.h"
16 #include "zypp/base/String.h"
18 #include "zypp/SourceFactory.h"
19 #include "zypp/source/Builtin.h"
20 #include "zypp/media/MediaAccess.h"
21 #include "zypp/ZYppCallbacks.h"
24 using namespace zypp::source;
26 ///////////////////////////////////////////////////////////////////
28 { /////////////////////////////////////////////////////////////////
30 media::MediaManager media_mgr;
32 ///////////////////////////////////////////////////////////////////
34 // CLASS NAME : SourceFactory::Impl
36 /** SourceFactory implementation. */
37 struct SourceFactory::Impl
39 /** Try to create a \a _SourceImpl kind of Source.
40 * \throw EXCEPTION if creation fails
42 template<class _SourceImpl>
43 static Source_Ref::Impl_Ptr createSourceImpl( const media::MediaId & media_r,
44 const SourceInfo &context )
46 std::cout << "pre pass type: " << _SourceImpl::typeString() << endl;
47 Source_Ref::Impl_Ptr impl( new _SourceImpl );
48 std::cout << "pass type: " << _SourceImpl::typeString() << endl;
49 // note, base_source is a tribool, if indeterminate we fallback to false
50 impl->factoryCtor( media_r, context.path(), context.alias(), context.cacheDir(), context.baseSource(), context.autorefresh() );
51 std::cout << "pass 2 type: " << _SourceImpl::typeString() << endl;
55 ///////////////////////////////////////////////////////////////////
57 ///////////////////////////////////////////////////////////////////
59 // CLASS NAME : SourceFactory
61 ///////////////////////////////////////////////////////////////////
63 ///////////////////////////////////////////////////////////////////
65 // METHOD NAME : SourceFactory::SourceFactory
68 SourceFactory::SourceFactory()
71 ///////////////////////////////////////////////////////////////////
73 // METHOD NAME : SourceFactory::~SourceFactory
76 SourceFactory::~SourceFactory()
79 ///////////////////////////////////////////////////////////////////
81 // METHOD NAME : SourceFactory::createFrom
82 // METHOD TYPE : Source
84 Source_Ref SourceFactory::createFrom( const Source_Ref::Impl_Ptr & impl_r )
86 return impl_r ? Source_Ref( impl_r ) : Source_Ref::noSource;
89 void SourceFactory::listProducts( const Url & url_r, ProductSet & products_r )
91 if (! url_r.isValid())
92 ZYPP_THROW( Exception("Empty URL passed to SourceFactory") );
95 media::MediaId id = media_mgr.open(url_r);
97 Pathname products_file = Pathname("media.1/products");
100 media_mgr.provideFile (id, products_file);
101 products_file = media_mgr.localPath (id, products_file);
102 scanProductsFile (products_file, products_r);
104 catch ( const Exception & excpt ) {
106 MIL << "No products description found on the Url" << endl;
109 media_mgr.release(id);
112 Source_Ref SourceFactory::createFrom( const source::SourceInfo &context )
114 if ( context.type().empty() )
116 return createFrom( context.url(),
120 context.baseSource() );
124 return createFrom( context.type(),
129 context.baseSource(),
130 context.autorefresh() );
134 template<typename _SourceImpl>
135 static bool probeSource(const Url &url_r, const Pathname &path_r, media::MediaId id, const std::string &type, callback::SendReport<ProbeSourceReport> &report )
139 boost::function<bool()> probe = typename _SourceImpl::Prober( id, path_r );
143 report->successProbe(url_r, type);
148 report->failedProbe(url_r, type);
152 catch (const Exception & excpt_r)
154 report->finish(url_r, ProbeSourceReport::UNKNOWN, excpt_r.asUserString());
159 template<class _SourceImpl>
160 Source_Ref SourceFactory::createSourceImplWorkflow( media::MediaId id, const SourceInfo &context )
162 MIL << "Trying (pre) to create source of type " << _SourceImpl::typeString() << endl;
163 callback::SendReport<SourceCreateReport> report;
167 report->start( context.url() );
170 MIL << "Trying to create source of type " << _SourceImpl::typeString() << endl;
171 Source_Ref::Impl_Ptr impl( Impl::createSourceImpl<_SourceImpl>( id, context ) );
172 std::cout << "created source " << impl->type() << endl;
173 report->finish( context.url(), SourceCreateReport::NO_ERROR, std::string() );
174 return Source_Ref(impl);
176 catch (const SourceUserRejectedException & excpt_r)
178 ZYPP_CAUGHT(excpt_r);
179 report->problem( context.url(), SourceCreateReport::REJECTED, "Source rejected by the user" );
180 report->finish( context.url(), SourceCreateReport::NO_ERROR, "" );
181 ZYPP_THROW(Exception( "Source Rejected: " + excpt_r.asUserString() ));
183 catch ( const SourceMetadataException & excpt_r )
185 ZYPP_CAUGHT(excpt_r);
186 report->problem( context.url(), SourceCreateReport::REJECTED, "Source metadata is invalid: " + excpt_r.asUserString() );
187 report->finish( context.url(), SourceCreateReport::REJECTED, "" );
188 ZYPP_THROW(Exception( "Invalid Source: " + excpt_r.asUserString() ));
190 catch (const Exception & excpt_r)
192 ZYPP_CAUGHT(excpt_r);
193 if ( report->problem( context.url(), SourceCreateReport::UNKNOWN, "Unknown Error: " + excpt_r.asUserString() ) != SourceCreateReport::RETRY )
195 report->finish( context.url(), SourceCreateReport::UNKNOWN, std::string("Unknown Error: ") + excpt_r.asUserString() );
196 ZYPP_THROW(Exception( "Unknown Error: " + excpt_r.asUserString() ));
204 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 )
206 if (! url_r.isValid())
207 ZYPP_THROW( Exception("Empty URL passed to SourceFactory") );
209 #warning if cache_dir is provided, no need to open the original url
211 media::MediaId id = media_mgr.open(url_r);
213 // add dummy verifier
214 media_mgr.addVerifier(id, media::MediaVerifierRef(new media::NoVerifier()));
215 // attach only if initializing from media and not from cache (#153073)
216 if (cache_dir_r == "")
218 media_mgr.attach(id);
222 MIL << "Initializing from cache" << endl;
225 bool auto_refresh = media::MediaAccess::canBeVolatile( url_r );
227 SourceInfo context( url_r, path_r, alias_r, cache_dir_r, auto_refresh );
228 context.setBaseSource( base_source );
230 callback::SendReport<ProbeSourceReport> report;
231 bool probeYUM, probeYaST;
233 report->start(url_r);
234 if ( probeYUM = probeSource<yum::YUMSourceImpl>( url_r, path_r, id, "YUM", report ) )
238 else if ( probeYaST = probeSource<susetags::SuseTagsImpl>( url_r, path_r, id, "YaST", report ) )
242 report->finish(url_r, ProbeSourceReport::NO_ERROR, "");
246 Source_Ref source(createSourceImplWorkflow<source::yum::YUMSourceImpl>( id, context ));
249 else if ( probeYaST )
251 Source_Ref source(createSourceImplWorkflow<susetags::SuseTagsImpl>( id, context ));
256 ZYPP_THROW( Exception("Unknown source type for " + url_r.asString() ) );
259 //////////////////////////////////////////////////////////////////
261 //////////////////////////////////////////////////////////////////
267 return Source_Ref(); // not reached!!
271 if ( ! ( ( url_r.getScheme() == "file") || ( url_r.getScheme() == "dir ") ) )
273 MIL << "Trying the Plaindir source" << endl;
274 //Source_Ref::Impl_Ptr impl( base_source
275 // ? Impl::createBaseSourceImpl<plaindir::PlaindirImpl>(id, path_r, alias_r, cache_dir_r, auto_refresh)
276 // : Impl::createSourceImpl<plaindir::PlaindirImpl>(id, path_r, alias_r, cache_dir_r, auto_refresh) );
277 MIL << "Using the Plaindir source" << endl;
278 //report->endProbe (url_r);
279 //return Source_Ref(impl);
284 ZYPP_THROW(Exception("Url scheme " + url_r.getScheme() + " not compatible with plaindir sources. Only local paths supported"));
287 catch (const Exception & excpt_r)
289 ZYPP_CAUGHT(excpt_r);
290 MIL << "Not Plaindir source, trying next type" << endl;
293 ERR << "No next type of source" << endl;
294 ZYPP_THROW(Exception("Cannot create the installation source"));
295 return Source_Ref(); // not reached!!
298 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 )
300 if (! url_r.isValid())
301 ZYPP_THROW( Exception("Empty URL passed to SourceFactory") );
303 //callback::SendReport<CreateSourceReport> report;
305 //report->startProbe (url_r);
307 #warning if cache_dir is provided, no need to open the original url
309 media::MediaId id = media_mgr.open(url_r);
311 // add dummy verifier
312 media_mgr.addVerifier(id, media::MediaVerifierRef(new media::NoVerifier()));
313 // attach only if initializing from media and not from cache (#153073)
314 if (cache_dir_r == "")
316 media_mgr.attach(id);
320 MIL << "Initializing from cache" << endl;
323 // Sane default for unknown autorefresh
324 if ( auto_refresh == indeterminate )
325 auto_refresh = media::MediaAccess::canBeVolatile( url_r );
327 SourceInfo context( url_r, path_r, alias_r, cache_dir_r, auto_refresh );
328 context.setBaseSource( base_source );
329 context.setType( type );
333 Source_Ref::Impl_Ptr impl;
335 if( type == yum::YUMSourceImpl::typeString() )
337 MIL << "Trying the YUM source" << endl;
338 impl = Source_Ref::Impl_Ptr( Impl::createSourceImpl<yum::YUMSourceImpl>(id, context ) );
339 MIL << "YUM source created" << endl;
341 else if ( type == susetags::SuseTagsImpl::typeString() )
343 MIL << "Trying the SUSE tags source" << endl;
344 impl = Source_Ref::Impl_Ptr( Impl::createSourceImpl<susetags::SuseTagsImpl>(id, context ) );
345 MIL << "YaST source created" << endl;
347 else if ( type == PlaindirImpl::typeString() )
349 MIL << "Trying the Plaindir source" << endl;
350 impl = Source_Ref::Impl_Ptr( Impl::createSourceImpl<PlaindirImpl>(id, context ) );
351 MIL << "Plaindir source created" << endl;
355 ZYPP_THROW( Exception ("Cannot create source of unknown type '" + type + "'"));
358 return Source_Ref(impl);
360 catch (const Exception & excpt_r)
362 ZYPP_CAUGHT(excpt_r);
363 MIL << "Creating a source of type " << type << " failed " << endl;
366 //report->endProbe (url_r);
368 ERR << "No next type of source" << endl;
369 ZYPP_THROW(Exception("Cannot create the installation source"));
370 return Source_Ref(); // not reached!!
374 /******************************************************************
376 ** FUNCTION NAME : operator<<
377 ** FUNCTION TYPE : std::ostream &
379 std::ostream & operator<<( std::ostream & str, const SourceFactory & obj )
381 return str << "SourceFactory";
384 void SourceFactory::scanProductsFile( const Pathname & file_r, ProductSet & pset_r ) const
386 std::ifstream pfile( file_r.asString().c_str() );
387 while ( pfile.good() ) {
389 std::string value = str::getline( pfile, str::TRIM );
391 ERR << "Error parsing " << file_r << endl;
392 ZYPP_THROW(Exception("Error parsing " + file_r.asString()));
394 if ( pfile.fail() ) {
395 break; // no data on last line
397 std::string tag = str::stripFirstWord( value, true );
400 pset_r.insert( ProductEntry( tag, value ) );
407 /////////////////////////////////////////////////////////////////
409 ///////////////////////////////////////////////////////////////////