comparison data/fileio/FileSource.cpp @ 713:b5daf8fc05ba library_integration

Merge from the default branch
author mathieub <mathieu.barthet@eecs.qmul.ac.uk>
date Mon, 10 Oct 2011 17:27:54 +0100
parents 579b2da21e7a
children 3b2409646cc0
comparison
equal deleted inserted replaced
710:773f228f080d 713:b5daf8fc05ba
75 m_http(0), 75 m_http(0),
76 m_localFile(0), 76 m_localFile(0),
77 m_preferredContentType(preferredContentType), 77 m_preferredContentType(preferredContentType),
78 m_ok(false), 78 m_ok(false),
79 m_lastStatus(0), 79 m_lastStatus(0),
80 m_resource(fileOrUrl.startsWith(':')),
80 m_remote(isRemote(fileOrUrl)), 81 m_remote(isRemote(fileOrUrl)),
81 m_done(false), 82 m_done(false),
82 m_leaveLocalFile(false), 83 m_leaveLocalFile(false),
83 m_reporter(reporter), 84 m_reporter(reporter),
84 m_refCounted(false) 85 m_refCounted(false)
85 { 86 {
87 if (m_resource) { // qrc file
88 m_url = QUrl("qrc" + fileOrUrl);
89 }
90
86 if (m_url.toString() == "") { 91 if (m_url.toString() == "") {
87 m_url = QUrl(fileOrUrl, QUrl::TolerantMode); 92 m_url = QUrl(fileOrUrl, QUrl::TolerantMode);
88 } 93 }
89 94
90 #ifdef DEBUG_FILE_SOURCE 95 #ifdef DEBUG_FILE_SOURCE
91 SVDEBUG << "FileSource::FileSource(" << fileOrUrl << "): url <" << m_url.toString() << ">" << endl; 96 std::cerr << "FileSource::FileSource(" << fileOrUrl << "): url <" << m_url.toString() << ">" << std::endl;
92 incCount(m_url.toString()); 97 incCount(m_url.toString());
93 #endif 98 #endif
94 99
95 if (!canHandleScheme(m_url)) { 100 if (!canHandleScheme(m_url)) {
96 SVDEBUG << "FileSource::FileSource: ERROR: Unsupported scheme in URL \"" << m_url.toString() << "\"" << endl; 101 SVDEBUG << "FileSource::FileSource: ERROR: Unsupported scheme in URL \"" << m_url.toString() << "\"" << endl;
101 init(); 106 init();
102 107
103 if (!isRemote() && 108 if (!isRemote() &&
104 !isAvailable()) { 109 !isAvailable()) {
105 #ifdef DEBUG_FILE_SOURCE 110 #ifdef DEBUG_FILE_SOURCE
106 std::cerr << "FileSource::FileSource: Failed to open local file with URL \"" << m_url.toString() << "; trying again assuming filename was encoded" << std::endl; 111 std::cerr << "FileSource::FileSource: Failed to open local file with URL \"" << m_url.toString() << "\"; trying again assuming filename was encoded" << std::endl;
107 #endif 112 #endif
108 m_url = QUrl::fromEncoded(fileOrUrl.toAscii()); 113 m_url = QUrl::fromEncoded(fileOrUrl.toAscii());
109 init(); 114 init();
110 } 115 }
111 116
157 m_ftp(0), 162 m_ftp(0),
158 m_http(0), 163 m_http(0),
159 m_localFile(0), 164 m_localFile(0),
160 m_ok(false), 165 m_ok(false),
161 m_lastStatus(0), 166 m_lastStatus(0),
167 m_resource(false),
162 m_remote(isRemote(url.toString())), 168 m_remote(isRemote(url.toString())),
163 m_done(false), 169 m_done(false),
164 m_leaveLocalFile(false), 170 m_leaveLocalFile(false),
165 m_reporter(reporter), 171 m_reporter(reporter),
166 m_refCounted(false) 172 m_refCounted(false)
189 m_ftp(0), 195 m_ftp(0),
190 m_http(0), 196 m_http(0),
191 m_localFile(0), 197 m_localFile(0),
192 m_ok(rf.m_ok), 198 m_ok(rf.m_ok),
193 m_lastStatus(rf.m_lastStatus), 199 m_lastStatus(rf.m_lastStatus),
200 m_resource(rf.m_resource),
194 m_remote(rf.m_remote), 201 m_remote(rf.m_remote),
195 m_done(false), 202 m_done(false),
196 m_leaveLocalFile(false), 203 m_leaveLocalFile(false),
197 m_reporter(rf.m_reporter), 204 m_reporter(rf.m_reporter),
198 m_refCounted(false) 205 m_refCounted(false)
253 } 260 }
254 261
255 void 262 void
256 FileSource::init() 263 FileSource::init()
257 { 264 {
258 if (!isRemote()) { 265 if (isResource()) {
259 #ifdef DEBUG_FILE_SOURCE 266 #ifdef DEBUG_FILE_SOURCE
260 SVDEBUG << "FileSource::init: Not a remote URL" << endl; 267 std::cerr << "FileSource::init: Is a resource" << std::endl;
268 #endif
269 QString resourceFile = m_url.toString();
270 resourceFile.replace(QRegExp("^qrc:"), ":");
271
272 if (!QFileInfo(resourceFile).exists()) {
273 #ifdef DEBUG_FILE_SOURCE
274 std::cerr << "FileSource::init: Resource file of this name does not exist, switching to non-resource URL" << std::endl;
275 #endif
276 m_url = resourceFile;
277 m_resource = false;
278 }
279 }
280
281 if (!isRemote() && !isResource()) {
282 #ifdef DEBUG_FILE_SOURCE
283 std::cerr << "FileSource::init: Not a remote URL" << std::endl;
261 #endif 284 #endif
262 bool literal = false; 285 bool literal = false;
263 m_localFilename = m_url.toLocalFile(); 286 m_localFilename = m_url.toLocalFile();
264 if (m_localFilename == "") { 287 if (m_localFilename == "") {
265 // QUrl may have mishandled the scheme (e.g. in a DOS path) 288 // QUrl may have mishandled the scheme (e.g. in a DOS path)
267 literal = true; 290 literal = true;
268 } 291 }
269 m_localFilename = QFileInfo(m_localFilename).absoluteFilePath(); 292 m_localFilename = QFileInfo(m_localFilename).absoluteFilePath();
270 293
271 #ifdef DEBUG_FILE_SOURCE 294 #ifdef DEBUG_FILE_SOURCE
272 SVDEBUG << "FileSource::init: URL translates to local filename \"" 295 std::cerr << "FileSource::init: URL translates to local filename \""
273 << m_localFilename << "\" (with literal=" << literal << ")" << endl; 296 << m_localFilename << "\" (with literal=" << literal << ")"
297 << std::endl;
274 #endif 298 #endif
275 m_ok = true; 299 m_ok = true;
276 m_lastStatus = 200; 300 m_lastStatus = 200;
277 301
278 if (!QFileInfo(m_localFilename).exists()) { 302 if (!QFileInfo(m_localFilename).exists()) {
279 if (literal) { 303 if (literal) {
280 m_lastStatus = 404; 304 m_lastStatus = 404;
281 } else { 305 } else {
282 #ifdef DEBUG_FILE_SOURCE 306 #ifdef DEBUG_FILE_SOURCE
283 SVDEBUG << "FileSource::init: Local file of this name does not exist, trying URL as a literal filename" << endl; 307 std::cerr << "FileSource::init: Local file of this name does not exist, trying URL as a literal filename" << std::endl;
284 #endif 308 #endif
285 // Again, QUrl may have been mistreating us -- 309 // Again, QUrl may have been mistreating us --
286 // e.g. dropping a part that looks like query data 310 // e.g. dropping a part that looks like query data
287 m_localFilename = m_url.toString(); 311 m_localFilename = m_url.toString();
288 literal = true; 312 literal = true;
296 return; 320 return;
297 } 321 }
298 322
299 if (createCacheFile()) { 323 if (createCacheFile()) {
300 #ifdef DEBUG_FILE_SOURCE 324 #ifdef DEBUG_FILE_SOURCE
301 SVDEBUG << "FileSource::init: Already have this one" << endl; 325 std::cerr << "FileSource::init: Already have this one" << std::endl;
302 #endif 326 #endif
303 m_ok = true; 327 m_ok = true;
304 if (!QFileInfo(m_localFilename).exists()) { 328 if (!QFileInfo(m_localFilename).exists()) {
305 m_lastStatus = 404; 329 m_lastStatus = 404;
306 } else { 330 } else {
309 m_done = true; 333 m_done = true;
310 return; 334 return;
311 } 335 }
312 336
313 if (m_localFilename == "") return; 337 if (m_localFilename == "") return;
338
314 m_localFile = new QFile(m_localFilename); 339 m_localFile = new QFile(m_localFilename);
315 m_localFile->open(QFile::WriteOnly); 340 m_localFile->open(QFile::WriteOnly);
316 341
317 QString scheme = m_url.scheme().toLower(); 342 if (isResource()) {
318 343
319 #ifdef DEBUG_FILE_SOURCE 344 // Absent resource file case was dealt with at the top -- this
320 SVDEBUG << "FileSource::init: Don't have local copy of \"" 345 // is the successful case
321 << m_url.toString() << "\", retrieving" << endl; 346
322 #endif 347 QString resourceFileName = m_url.toString();
323 348 resourceFileName.replace(QRegExp("^qrc:"), ":");
324 if (scheme == "http") { 349 QFile resourceFile(resourceFileName);
325 initHttp(); 350 resourceFile.open(QFile::ReadOnly);
326 #ifdef DEBUG_FILE_SOURCE 351 QByteArray ba(resourceFile.readAll());
327 std::cerr << "FileSource: initHttp succeeded" << std::endl; 352
328 #endif 353 #ifdef DEBUG_FILE_SOURCE
329 } else if (scheme == "ftp") { 354 std::cerr << "Copying " << ba.size() << " bytes from resource file to cache file" << std::endl;
330 initFtp(); 355 #endif
356
357 qint64 written = m_localFile->write(ba);
358 m_localFile->close();
359 delete m_localFile;
360 m_localFile = 0;
361
362 if (written != ba.size()) {
363 #ifdef DEBUG_FILE_SOURCE
364 std::cerr << "Copy failed (wrote " << written << " bytes)" << std::endl;
365 #endif
366 m_ok = false;
367 return;
368 } else {
369 m_ok = true;
370 m_lastStatus = 200;
371 m_done = true;
372 }
373
331 } else { 374 } else {
332 m_remote = false; 375
333 m_ok = false; 376 QString scheme = m_url.scheme().toLower();
377
378 #ifdef DEBUG_FILE_SOURCE
379 std::cerr << "FileSource::init: Don't have local copy of \""
380 << m_url.toString() << "\", retrieving" << std::endl;
381 #endif
382
383 if (scheme == "http") {
384 initHttp();
385 #ifdef DEBUG_FILE_SOURCE
386 std::cerr << "FileSource: initHttp succeeded" << std::endl;
387 #endif
388 } else if (scheme == "ftp") {
389 initFtp();
390 } else {
391 m_remote = false;
392 m_ok = false;
393 }
334 } 394 }
335 395
336 if (m_ok) { 396 if (m_ok) {
337 397
338 QMutexLocker locker(&m_mapMutex); 398 QMutexLocker locker(&m_mapMutex);
341 // someone else has been doing the same thing at the same time, 401 // someone else has been doing the same thing at the same time,
342 // but has got there first 402 // but has got there first
343 cleanup(); 403 cleanup();
344 m_refCountMap[m_url]++; 404 m_refCountMap[m_url]++;
345 #ifdef DEBUG_FILE_SOURCE 405 #ifdef DEBUG_FILE_SOURCE
346 SVDEBUG << "FileSource::init: Another FileSource has got there first, abandoning our download and using theirs" << endl; 406 std::cerr << "FileSource::init: Another FileSource has got there first, abandoning our download and using theirs" << std::endl;
347 #endif 407 #endif
348 m_localFilename = m_remoteLocalMap[m_url]; 408 m_localFilename = m_remoteLocalMap[m_url];
349 m_refCounted = true; 409 m_refCounted = true;
350 m_ok = true; 410 m_ok = true;
351 if (!QFileInfo(m_localFilename).exists()) { 411 if (!QFileInfo(m_localFilename).exists()) {
357 417
358 m_remoteLocalMap[m_url] = m_localFilename; 418 m_remoteLocalMap[m_url] = m_localFilename;
359 m_refCountMap[m_url]++; 419 m_refCountMap[m_url]++;
360 m_refCounted = true; 420 m_refCounted = true;
361 421
362 if (m_reporter) { 422 if (m_reporter && !m_done) {
363 m_reporter->setMessage 423 m_reporter->setMessage
364 (tr("Downloading %1...").arg(m_url.toString())); 424 (tr("Downloading %1...").arg(m_url.toString()));
365 connect(m_reporter, SIGNAL(cancelled()), this, SLOT(cancelled())); 425 connect(m_reporter, SIGNAL(cancelled()), this, SLOT(cancelled()));
366 connect(this, SIGNAL(progress(int)), 426 connect(this, SIGNAL(progress(int)),
367 m_reporter, SLOT(setProgress(int))); 427 m_reporter, SLOT(setProgress(int)));
515 FileSource::canHandleScheme(QUrl url) 575 FileSource::canHandleScheme(QUrl url)
516 { 576 {
517 // Note that a "scheme" with length 1 is probably a DOS drive letter 577 // Note that a "scheme" with length 1 is probably a DOS drive letter
518 QString scheme = url.scheme().toLower(); 578 QString scheme = url.scheme().toLower();
519 return (scheme == "http" || scheme == "ftp" || 579 return (scheme == "http" || scheme == "ftp" ||
520 scheme == "file" || scheme == "" || scheme.length() == 1); 580 scheme == "file" || scheme == "qrc" ||
581 scheme == "" || scheme.length() == 1);
521 } 582 }
522 583
523 bool 584 bool
524 FileSource::isAvailable() 585 FileSource::isAvailable()
525 { 586 {
567 628
568 bool 629 bool
569 FileSource::isDone() const 630 FileSource::isDone() const
570 { 631 {
571 return m_done; 632 return m_done;
633 }
634
635 bool
636 FileSource::isResource() const
637 {
638 return m_resource;
572 } 639 }
573 640
574 bool 641 bool
575 FileSource::isRemote() const 642 FileSource::isRemote() const
576 { 643 {
879 } 946 }
880 947
881 QString filepath(dir.filePath(filename)); 948 QString filepath(dir.filePath(filename));
882 949
883 #ifdef DEBUG_FILE_SOURCE 950 #ifdef DEBUG_FILE_SOURCE
884 SVDEBUG << "FileSource::createCacheFile: URL is \"" << m_url.toString() << "\", dir is \"" << dir.path() << "\", base \"" << base << "\", extension \"" << extension << "\", filebase \"" << filename << "\", filename \"" << filepath << "\"" << endl; 951 std::cerr << "FileSource::createCacheFile: URL is \"" << m_url.toString() << "\", dir is \"" << dir.path() << "\", base \"" << base << "\", extension \"" << extension << "\", filebase \"" << filename << "\", filename \"" << filepath << "\"" << std::endl;
885 #endif 952 #endif
886 953
887 QMutexLocker fcLocker(&m_fileCreationMutex); 954 QMutexLocker fcLocker(&m_fileCreationMutex);
888 955
889 ++m_count; 956 ++m_count;
916 return ""; 983 return "";
917 } 984 }
918 } 985 }
919 986
920 #ifdef DEBUG_FILE_SOURCE 987 #ifdef DEBUG_FILE_SOURCE
921 SVDEBUG << "FileSource::createCacheFile: url " 988 std::cerr << "FileSource::createCacheFile: url "
922 << m_url.toString() << " -> local filename " 989 << m_url.toString() << " -> local filename "
923 << filepath << endl; 990 << filepath << std::endl;
924 #endif 991 #endif
925 992
926 m_localFilename = filepath; 993 m_localFilename = filepath;
927 994
928 return false; 995 return false;