public synchronized Entry get(final JobContext jc) {
   jc.setCancelListener(
       new CancelListener() {
         @Override
         public void onCancel() {
           mTask.removeProxy(TaskProxy.this);
           synchronized (TaskProxy.this) {
             mIsCancelled = true;
             TaskProxy.this.notifyAll();
           }
         }
       });
   while (!mIsCancelled && mEntry == null) {
     try {
       wait();
     } catch (final InterruptedException e) {
       Log.w(TAG, "ignore interrupt", e);
     }
   }
   jc.setCancelListener(null);
   return mEntry;
 }
 @Override
 public File run(final JobContext jc) {
   // TODO: utilize etag
   jc.setMode(ThreadPool.MODE_NETWORK);
   File tempFile = null;
   try {
     final URL url = new URL(mUrl);
     tempFile = File.createTempFile("cache", ".tmp", mRoot);
     // download from url to tempFile
     jc.setMode(ThreadPool.MODE_NETWORK);
     final boolean downloaded = DownloadUtils.requestDownload(jc, url, tempFile);
     jc.setMode(ThreadPool.MODE_NONE);
     if (downloaded) return tempFile;
   } catch (final Exception e) {
     Log.e(TAG, String.format("fail to download %s", mUrl), e);
   } finally {
     jc.setMode(ThreadPool.MODE_NONE);
   }
   if (tempFile != null) {
     tempFile.delete();
   }
   return null;
 }