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 static media::MediaManager & media_mgr()
32 static media::MediaManager _v;
36 ///////////////////////////////////////////////////////////////////
38 // CLASS NAME : SourceFactory::Impl
40 /** SourceFactory implementation. */
41 struct SourceFactory::Impl
43 /** Try to create a \a _SourceImpl kind of Source.
44 * \throw EXCEPTION if creation fails
46 template<class _SourceImpl>
47 static Source_Ref::Impl_Ptr createSourceImpl( const media::MediaId & media_r,
48 const SourceInfo &context )
50 Source_Ref::Impl_Ptr impl( new _SourceImpl );
51 // note, base_source is a tribool, if indeterminate we fallback to false
52 //MIL << "Going to call factory ctor:" << endl;
53 //MIL << context << endl;
54 impl->factoryCtor( media_r, context.path(), context.alias(), context.cacheDir(), context.baseSource(), context.autorefresh() );
58 ///////////////////////////////////////////////////////////////////
60 ///////////////////////////////////////////////////////////////////
62 // CLASS NAME : SourceFactory
64 ///////////////////////////////////////////////////////////////////
66 ///////////////////////////////////////////////////////////////////
68 // METHOD NAME : SourceFactory::SourceFactory
71 SourceFactory::SourceFactory()
74 ///////////////////////////////////////////////////////////////////
76 // METHOD NAME : SourceFactory::~SourceFactory
79 SourceFactory::~SourceFactory()
82 ///////////////////////////////////////////////////////////////////
84 // METHOD NAME : SourceFactory::createFrom
85 // METHOD TYPE : Source
87 Source_Ref SourceFactory::createFrom( const Source_Ref::Impl_Ptr & impl_r )
89 return impl_r ? Source_Ref( impl_r ) : Source_Ref::noSource;
92 void SourceFactory::listProducts( const Url & url_r, ProductSet & products_r )
94 if (! url_r.isValid())
95 ZYPP_THROW( Exception("Empty URL passed to SourceFactory") );
98 media::MediaId id = media_mgr().open(url_r);
99 media_mgr().attach(id);
100 Pathname products_file = Pathname("media.1/products");
103 media_mgr().provideFile (id, products_file);
104 products_file = media_mgr().localPath (id, products_file);
105 scanProductsFile (products_file, products_r);
107 catch ( const Exception & excpt ) {
109 MIL << "No products description found on the Url" << endl;
112 media_mgr().release(id);
115 Source_Ref SourceFactory::createFrom( const source::SourceInfo &context )
117 if ( context.type().empty() )
119 return createFrom( context.url(),
123 context.baseSource() );
127 return createFrom( context.type(),
132 context.baseSource(),
133 context.autorefresh() );
137 template<typename _SourceImpl>
138 static bool probeSource(const Url &url_r, const Pathname &path_r, media::MediaId id, const std::string &type, callback::SendReport<ProbeSourceReport> &report )
140 boost::function<bool()> probe = typename _SourceImpl::Prober( id, path_r );
144 report->successProbe(url_r, type);
149 report->failedProbe(url_r, type);
155 template<class _SourceImpl>
156 Source_Ref SourceFactory::createSourceImplWorkflow( media::MediaId id, const SourceInfo &context )
158 //MIL << "Trying (pre) to create source of type " << _SourceImpl::typeString() << endl;
159 callback::SendReport<SourceCreateReport> report;
163 report->start( context.url() );
166 MIL << "Trying to create source of type " << _SourceImpl::typeString() << endl;
167 Source_Ref::Impl_Ptr impl( Impl::createSourceImpl<_SourceImpl>( id, context ) );
168 MIL << "Created source " << impl->type() << endl;
169 report->finish( context.url(), SourceCreateReport::NO_ERROR, std::string() );
170 return Source_Ref(impl);
172 catch (const SourceUserRejectedException & excpt_r)
174 ZYPP_CAUGHT(excpt_r);
175 report->problem( context.url(), SourceCreateReport::REJECTED, "Source rejected by the user" );
176 report->finish( context.url(), SourceCreateReport::NO_ERROR, "" );
177 ZYPP_THROW(Exception( "Source Rejected: " + excpt_r.asUserString() ));
179 catch ( const SourceMetadataException & excpt_r )
181 ZYPP_CAUGHT(excpt_r);
182 report->problem( context.url(), SourceCreateReport::REJECTED, "Source metadata is invalid: " + excpt_r.asUserString() );
183 report->finish( context.url(), SourceCreateReport::REJECTED, "" );
184 ZYPP_THROW(Exception( "Invalid Source: " + excpt_r.asUserString() ));
186 catch (const Exception & excpt_r)
188 ZYPP_CAUGHT(excpt_r);
189 if ( report->problem( context.url(), SourceCreateReport::UNKNOWN, "Unknown Error: " + excpt_r.asUserString() ) != SourceCreateReport::RETRY )
191 report->finish( context.url(), SourceCreateReport::UNKNOWN, std::string("Unknown Error: ") + excpt_r.asUserString() );
192 ZYPP_THROW(Exception( "Unknown Error: " + excpt_r.asUserString() ));
200 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 )
202 if (! url_r.isValid())
203 ZYPP_THROW( Exception("Empty URL passed to SourceFactory") );
205 #warning if cache_dir is provided, no need to open the original url
207 media::MediaId id = media_mgr().open(url_r);
209 // add dummy verifier
210 media_mgr().addVerifier(id, media::MediaVerifierRef(new media::NoVerifier()));
211 // attach only if initializing from media and not from cache (#153073)
212 if (cache_dir_r == "")
214 media_mgr().attach(id);
218 MIL << "Initializing from cache" << endl;
221 bool auto_refresh = media::MediaAccess::canBeVolatile( url_r );
223 SourceInfo context( url_r, path_r, alias_r, cache_dir_r, auto_refresh );
224 context.setBaseSource( base_source );
226 callback::SendReport<ProbeSourceReport> report;
227 bool probeYUM = false;
228 bool probeYaST = false;
230 report->start(url_r);
233 if ( (probeYUM = probeSource<yum::YUMSourceImpl>( url_r, path_r, id, "YUM", report )) )
237 else if ( (probeYaST = probeSource<susetags::SuseTagsImpl>( url_r, path_r, id, "YaST", report )) )
241 report->finish(url_r, ProbeSourceReport::NO_ERROR, "");
245 Source_Ref source(createSourceImplWorkflow<source::yum::YUMSourceImpl>( id, context ));
248 else if ( probeYaST )
250 Source_Ref source(createSourceImplWorkflow<susetags::SuseTagsImpl>( id, context ));
255 ZYPP_THROW( SourceUnknownTypeException("Unknown source type for " + url_r.asString() ) );
258 catch ( const Exception &e )
260 report->finish(url_r, ProbeSourceReport::IO, e.asUserString());
263 //////////////////////////////////////////////////////////////////
265 //////////////////////////////////////////////////////////////////
268 return Source_Ref(); // not reached!!
271 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 )
273 if (! url_r.isValid())
274 ZYPP_THROW( Exception("Empty URL passed to SourceFactory") );
276 //callback::SendReport<CreateSourceReport> report;
278 //report->startProbe (url_r);
280 #warning if cache_dir is provided, no need to open the original url
282 media::MediaId id = media_mgr().open(url_r);
284 // add dummy verifier
285 media_mgr().addVerifier(id, media::MediaVerifierRef(new media::NoVerifier()));
286 // attach only if initializing from media and not from cache (#153073)
287 if (cache_dir_r == "")
289 media_mgr().attach(id);
293 MIL << "Initializing from cache" << endl;
296 bool calculated_autorefresh = auto_refresh;
297 // Sane default for unknown autorefresh
298 if ( auto_refresh == indeterminate )
299 calculated_autorefresh = media::MediaAccess::canBeVolatile( url_r );
301 //SourceInfo( url, path, alias, cache_dir, autorefresh );
302 SourceInfo context( url_r, path_r, alias_r, cache_dir_r, calculated_autorefresh );
303 context.setBaseSource( base_source );
304 context.setType( type );
308 Source_Ref::Impl_Ptr impl;
310 if( type == yum::YUMSourceImpl::typeString() )
312 MIL << "Trying the YUM source" << endl;
313 impl = Source_Ref::Impl_Ptr( Impl::createSourceImpl<yum::YUMSourceImpl>(id, context ) );
314 MIL << "YUM source created" << endl;
316 else if ( type == susetags::SuseTagsImpl::typeString() )
318 MIL << "Trying the SUSE tags source" << endl;
319 impl = Source_Ref::Impl_Ptr( Impl::createSourceImpl<susetags::SuseTagsImpl>(id, context ) );
320 MIL << "YaST source created" << endl;
322 else if ( type == PlaindirImpl::typeString() )
324 MIL << "Trying the Plaindir source" << endl;
325 impl = Source_Ref::Impl_Ptr( Impl::createSourceImpl<PlaindirImpl>(id, context ) );
326 MIL << "Plaindir source created" << endl;
330 ZYPP_THROW( Exception ("Cannot create source of unknown type '" + type + "'"));
334 return Source_Ref(impl);
336 catch (const Exception & excpt_r)
338 ZYPP_CAUGHT(excpt_r);
339 MIL << "Creating a source of type " << type << " failed " << endl;
340 ZYPP_RETHROW(excpt_r);
343 return Source_Ref(); // not reached!!
347 /******************************************************************
349 ** FUNCTION NAME : operator<<
350 ** FUNCTION TYPE : std::ostream &
352 std::ostream & operator<<( std::ostream & str, const SourceFactory & obj )
354 return str << "SourceFactory";
357 void SourceFactory::scanProductsFile( const Pathname & file_r, ProductSet & pset_r ) const
359 std::ifstream pfile( file_r.asString().c_str() );
360 while ( pfile.good() ) {
362 std::string value = str::getline( pfile, str::TRIM );
364 ERR << "Error parsing " << file_r << endl;
365 ZYPP_THROW(Exception("Error parsing " + file_r.asString()));
367 if ( pfile.fail() ) {
368 break; // no data on last line
370 std::string tag = str::stripFirstWord( value, true );
373 pset_r.insert( ProductEntry( tag, value ) );
380 /////////////////////////////////////////////////////////////////
382 ///////////////////////////////////////////////////////////////////