1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
13 #include "zypp/base/LogTools.h"
14 #include "zypp/base/UserRequestException.h"
15 #include "zypp/ZYppCallbacks.h"
16 #include "zypp/MediaSetAccess.h"
17 #include "zypp/PathInfo.h"
18 //#include "zypp/source/MediaSetAccessReportReceivers.h"
22 ///////////////////////////////////////////////////////////////////
24 { /////////////////////////////////////////////////////////////////
26 IMPL_PTR_TYPE(MediaSetAccess);
28 ///////////////////////////////////////////////////////////////////
30 MediaSetAccess::MediaSetAccess(const Url &url,
31 const Pathname & prefered_attach_point)
33 _prefAttachPoint(prefered_attach_point)
35 MIL << "initializing.." << std::endl;
36 //std::vector<media::MediaVerifierRef> single_media;
37 //single_media[0] = media::MediaVerifierRef(new media::NoVerifier());
38 //_verifiers = single_media;
42 MediaSetAccess::~MediaSetAccess()
48 void MediaSetAccess::setVerifier( unsigned media_nr, media::MediaVerifierRef verifier )
50 if (_medias.find(media_nr) != _medias.end())
52 // the media already exists, set theverifier
53 media::MediaAccessId id = _medias[media_nr];
54 media::MediaManager media_mgr;
55 media_mgr.addVerifier( id, verifier );
56 // remove any saved verifier for this media
57 _verifiers.erase(media_nr);
58 //if (! noattach && ! media_mgr.isAttached(id))
59 //media_mgr.attach(id);
63 // save the verifier in the map, and set it when
64 // the media number is first attached
65 _verifiers[media_nr] = verifier;
69 // callback::SendReport<source::DownloadFileReport> report;
70 // DownloadProgressFileReceiver download_report( report );
71 // SourceFactory source_factory;
72 // Url file_url( url().asString() + file_r.asString() );
73 // report->start( source_factory.createFrom(this), file_url );
74 // callback::TempConnect<media::DownloadProgressReport> tmp_download( download_report );
75 // Pathname file = provideJustFile( file_r, media_nr, cached, checkonly );
76 // report->finish( file_url, source::DownloadFileReport::NO_ERROR, "" );
80 Pathname MediaSetAccess::provideFile( const OnMediaLocation & on_media_file )
82 return provideFile( on_media_file.filename(), on_media_file.medianr() );
86 Pathname MediaSetAccess::provideFile(const Pathname & file, unsigned media_nr )
88 return provideFileInternal( file, media_nr, false, false);
91 bool MediaSetAccess::doesFileExist(const Pathname & file, unsigned media_nr )
93 callback::SendReport<media::MediaChangeReport> report;
94 media::MediaManager media_mgr;
95 // get the mediaId, but don't try to attach it here
96 media::MediaAccessId media = getMediaAccessId( media_nr);
104 DBG << "Cheking if file " << file
105 << " from media number " << media_nr << " exists." << endl;
106 // try to attach the media
107 if ( ! media_mgr.isAttached(media) )
108 media_mgr.attachDesiredMedia(media);
109 exists = media_mgr.doesFileExist(media, file);
112 catch ( media::MediaException & excp )
115 media::MediaChangeReport::Action user;
118 DBG << "Media couldn't provide file " << file << " , releasing." << endl;
121 media_mgr.release (media, false);
123 catch (const Exception & excpt_r)
125 ZYPP_CAUGHT(excpt_r);
126 MIL << "Failed to release media " << media << endl;
130 media::MediaChangeReport::Error reason = media::MediaChangeReport::INVALID;
132 if( typeid(excp) == typeid( media::MediaFileNotFoundException ) ||
133 typeid(excp) == typeid( media::MediaNotAFileException ) )
135 reason = media::MediaChangeReport::NOT_FOUND;
137 else if( typeid(excp) == typeid( media::MediaNotDesiredException) ||
138 typeid(excp) == typeid( media::MediaNotAttachedException) )
140 reason = media::MediaChangeReport::WRONG;
143 user = media::MediaChangeReport::ABORT;
144 DBG << "doesFileExist exception caught, callback answer: " << user << endl;
146 if( user == media::MediaChangeReport::ABORT )
148 DBG << "Aborting" << endl;
149 ZYPP_RETHROW ( excp );
151 else if ( user == media::MediaChangeReport::IGNORE )
153 DBG << "Skipping" << endl;
154 ZYPP_THROW ( SkipRequestException("User-requested skipping of a file") );
156 else if ( user == media::MediaChangeReport::EJECT )
158 DBG << "Eject: try to release" << endl;
161 //zypp::SourceManager::sourceManager()->releaseAllSources();
163 catch (const zypp::Exception& excpt_r)
165 ZYPP_CAUGHT(excpt_r);
166 ERR << "Failed to release all sources" << endl;
168 media_mgr.release (media, true); // one more release needed for eject
169 // FIXME: this will not work, probably
171 else if ( user == media::MediaChangeReport::RETRY ||
172 user == media::MediaChangeReport::CHANGE_URL )
175 DBG << "Going to try again" << endl;
177 // not attaching, media set will do that for us
178 // this could generate uncaught exception (#158620)
183 DBG << "Don't know, let's ABORT" << endl;
184 ZYPP_RETHROW ( excp );
186 } while( user == media::MediaChangeReport::EJECT );
189 // retry or change URL
195 Pathname MediaSetAccess::provideFileInternal(const Pathname & file, unsigned media_nr, bool cached, bool checkonly )
197 callback::SendReport<media::MediaChangeReport> report;
198 media::MediaManager media_mgr;
199 // get the mediaId, but don't try to attach it here
200 media::MediaAccessId media = getMediaAccessId( media_nr);
206 DBG << "Going to try to provide file " << file
207 << " from media number " << media_nr << endl;
208 // try to attach the media
209 if ( ! media_mgr.isAttached(media) )
210 media_mgr.attachDesiredMedia(media);
211 media_mgr.provideFile (media, file, false, false);
214 catch ( media::MediaException & excp )
217 media::MediaChangeReport::Action user;
220 DBG << "Media couldn't provide file " << file << " , releasing." << endl;
223 media_mgr.release (media, false);
225 catch (const Exception & excpt_r)
227 ZYPP_CAUGHT(excpt_r);
228 MIL << "Failed to release media " << media << endl;
232 media::MediaChangeReport::Error reason = media::MediaChangeReport::INVALID;
234 if( typeid(excp) == typeid( media::MediaFileNotFoundException ) ||
235 typeid(excp) == typeid( media::MediaNotAFileException ) )
237 reason = media::MediaChangeReport::NOT_FOUND;
239 else if( typeid(excp) == typeid( media::MediaNotDesiredException) ||
240 typeid(excp) == typeid( media::MediaNotAttachedException) )
242 reason = media::MediaChangeReport::WRONG;
245 // request media change, if the media is changeable and this is
246 // not just a check, otherwise just abort
247 if (checkonly || !media_mgr.isChangeable(media))
248 user = media::MediaChangeReport::ABORT;
251 report->requestMedia (
252 Repository::noRepository,
258 DBG << "ProvideFile exception caught, callback answer: " << user << endl;
260 if( user == media::MediaChangeReport::ABORT )
262 DBG << "Aborting" << endl;
263 ZYPP_RETHROW ( excp );
265 else if ( user == media::MediaChangeReport::IGNORE )
267 DBG << "Skipping" << endl;
268 ZYPP_THROW ( SkipRequestException("User-requested skipping of a file") );
270 else if ( user == media::MediaChangeReport::EJECT )
272 DBG << "Eject: try to release" << endl;
275 //zypp::SourceManager::sourceManager()->releaseAllSources();
277 catch (const zypp::Exception& excpt_r)
279 ZYPP_CAUGHT(excpt_r);
280 ERR << "Failed to release all sources" << endl;
282 media_mgr.release (media, true); // one more release needed for eject
283 // FIXME: this will not work, probably
285 else if ( user == media::MediaChangeReport::RETRY ||
286 user == media::MediaChangeReport::CHANGE_URL )
289 DBG << "Going to try again" << endl;
291 // not attaching, media set will do that for us
292 // this could generate uncaught exception (#158620)
297 DBG << "Don't know, let's ABORT" << endl;
298 ZYPP_RETHROW ( excp );
300 } while( user == media::MediaChangeReport::EJECT );
303 // retry or change URL
306 return media_mgr.localPath( media, file );
310 Pathname MediaSetAccess::provideDir(const Pathname & dir,
314 callback::SendReport<media::MediaChangeReport> report;
315 media::MediaManager media_mgr;
317 // get the mediaId, but don't try to attach it here
318 media::MediaAccessId _media = getMediaAccessId(media_nr);
323 DBG << "Going to try provide direcotry " << dir
324 << (recursive ? " (recursively)" : "")
325 << " from media nr. " << media_nr << endl;
327 // try to attach the media
328 if (!media_mgr.isAttached(_media))
329 media_mgr.attachDesiredMedia(_media);
331 _media = getMediaAccessId(media_nr); // in case of redirect
334 media_mgr.provideDirTree(_media, dir);
336 media_mgr.provideDir(_media, dir);
338 break; // quit the retry loop
340 catch (media::MediaException & excp)
343 media::MediaChangeReport::Action user;
347 DBG << "Media couldn't provide dir " << dir << ", releasing." << endl;
350 media_mgr.release (_media, false);
352 catch (const Exception & excpt_r)
354 ZYPP_CAUGHT(excpt_r);
355 ERR << "Failed to release media " << _media << endl;
358 //MIL << "Releasing all medias of all sources" << endl;
361 //! \todo do we need replacement for this at all?
362 //zypp::SourceManager::sourceManager()->releaseAllSources();
364 catch (const zypp::Exception& excpt_r)
366 ZYPP_CAUGHT(excpt_r);
367 ERR << "Failed to release all sources" << endl;
371 media::MediaChangeReport::Error reason = media::MediaChangeReport::INVALID;
373 if (typeid(excp) == typeid(media::MediaFileNotFoundException)
374 || typeid(excp) == typeid(media::MediaNotAFileException))
376 reason = media::MediaChangeReport::NOT_FOUND;
378 else if (typeid(excp) == typeid( media::MediaNotDesiredException)
379 || typeid(excp) == typeid(media::MediaNotAttachedException))
381 reason = media::MediaChangeReport::WRONG;
385 // request media change, if the media is changeable, otherwise just abort
386 if (media_mgr.isChangeable(_media))
388 report->requestMedia(
389 Repository::noRepository,
395 user = media::MediaChangeReport::ABORT;
397 DBG << "ProvideFile exception caught, callback answer: " << user << endl;
399 if (user == media::MediaChangeReport::ABORT)
401 DBG << "Aborting" << endl;
402 ZYPP_RETHROW ( excp );
404 else if (user == media::MediaChangeReport::EJECT)
406 DBG << "Eject: try to release" << endl;
409 //! \todo do we need replacement for this at all?
410 // zypp::SourceManager::sourceManager()->releaseAllSources();
412 catch (const zypp::Exception& excpt_r)
414 ZYPP_CAUGHT(excpt_r);
415 ERR << "Failed to release all sources" << endl;
417 media_mgr.release (_media, true); // one more release needed for eject
418 // FIXME: this will not work, probably
420 else if (user == media::MediaChangeReport::RETRY ||
421 user == media::MediaChangeReport::CHANGE_URL)
424 DBG << "Going to try again" << endl;
426 // not attaching, media set will do that for us
427 // this could generate uncaught exception (#158620)
433 DBG << "Don't know, let's ABORT" << endl;
438 while (user == media::MediaChangeReport::EJECT);
440 // retry or change URL
444 return media_mgr.localPath(_media, dir);
447 media::MediaAccessId MediaSetAccess::getMediaAccessId (media::MediaNr medianr)
449 media::MediaManager media_mgr;
451 if (_medias.find(medianr) != _medias.end())
453 media::MediaAccessId id = _medias[medianr];
454 //if (! noattach && ! media_mgr.isAttached(id))
455 //media_mgr.attach(id);
459 url = rewriteUrl (_url, medianr);
460 media::MediaAccessId id = media_mgr.open(url, _prefAttachPoint);
461 _medias[medianr] = id;
465 if (_verifiers.find(medianr) != _verifiers.end())
467 // a verifier is set for this media
468 // FIXME check the case where the verifier exists
469 // but we have no access id for the media
470 media::MediaAccessId id = _medias[medianr];
471 media::MediaManager media_mgr;
472 media_mgr.delVerifier(id);
473 media_mgr.addVerifier( id, _verifiers[medianr] );
474 // remove any saved verifier for this media
475 _verifiers.erase(medianr);
478 catch ( const Exception &e )
481 WAR << "Verifier not found" << endl;
488 Url MediaSetAccess::rewriteUrl (const Url & url_r, const media::MediaNr medianr)
490 std::string scheme = url_r.getScheme();
491 if (scheme == "cd" || scheme == "dvd")
494 DBG << "Rewriting url " << url_r << endl;
498 // TODO the iso parameter will not be required in the future, this
499 // code has to be adapted together with the MediaISO change.
500 // maybe some MediaISOURL interface should be used.
501 std::string isofile = url_r.getQueryParam("iso");
502 boost::regex e("^(.*(cd|dvd))([0-9]+)(\\.iso)$", boost::regex::icase);
504 if(boost::regex_match(isofile, what, e, boost::match_extra))
507 isofile = what[1] + str::numstring(medianr) + what[4];
508 url.setQueryParam("iso", isofile);
509 DBG << "Url rewrite result: " << url << endl;
515 std::string pathname = url_r.getPathName();
516 boost::regex e("^(.*(cd|dvd))([0-9]+)(/?)$", boost::regex::icase);
518 if(boost::regex_match(pathname, what, e, boost::match_extra))
521 pathname = what[1] + str::numstring(medianr) + what[4];
522 url.setPathName(pathname);
523 DBG << "Url rewrite result: " << url << endl;
530 void MediaSetAccess::release()
532 DBG << "Releasing all media IDs held by this MediaSetAccess" << endl;
533 media::MediaManager manager;
534 for (MediaMap::const_iterator m = _medias.begin(); m != _medias.end(); ++m)
535 manager.release(m->second);
538 std::ostream & MediaSetAccess::dumpOn( std::ostream & str ) const
540 str << "MediaSetAccess (URL='" << _url << "', attach_point_hint='" << _prefAttachPoint << "')";
544 // media::MediaVerifierRef MediaSetAccess::verifier(unsigned media_nr)
545 // { return media::MediaVerifierRef(new media::NoVerifier()); }
547 /////////////////////////////////////////////////////////////////
549 ///////////////////////////////////////////////////////////////////