Program: 87348
Project: 87348
Buggy source:
/** 
 * Kicks off an asynchronous scraping job and returns a proxy object. This proxy is only for added convenience of monitoring/cancelling the job. The listener you pass as a parameter does all this and more already.
 * @param request The scraping request, built in accordance with http://usebobik.com/api/docs#func_ref
 * @param listener An object encapsulating various useful callbacks
 * @return proxy to monitor/abort the scraping job
 * @throws BobikException thrown on all Bobik-specific errors
 * @throws IOException thrown on network problems
 * @throws JSONException not common, thrown on surprise JSON parsing errors
 * @throws ExecutionException not common, thrown if there's a client-level error during the scheduling of threads
 * @throws InterruptedException not common, thrown if there's a client-level error during the scheduling of threads
 */
public Job scrape(JSONObject request,final JobListener listener) throws BobikException, IOException, JSONException, ExecutionException, InterruptedException {
  JSONObject job_submission=callAPI(request,"String_Node_Str");
  final long startTime=System.currentTimeMillis();
  final String job_id=getJobIdOrFail(job_submission);
  final Job job=new Job(){
    private JSONObject scraped_data=null;
    private Future<Object> job_waiter=null;
    private int estimated_completion_time_ms=-1;
    private boolean cancelled=false;
    private JSONObject getStatusRequestObj(    boolean download_results) throws BobikException, JSONException {
      JSONObject progress_check=new JSONObject();
      progress_check.accumulate(BobikConstants.JOB_TOKEN_LABEL,id());
      progress_check.accumulate(BobikConstants.SKIP_DATA_TOKEN_LABEL,!download_results);
      return progress_check;
    }
    @Override public String id(){
      return job_id;
    }
    @Override public float getProgress() throws BobikException {
      try {
        JSONObject status_check=callAPI(getStatusRequestObj(false),"String_Node_Str");
        processErrors(status_check,listener);
        float progress=(float)status_check.getDouble(BobikConstants.PROGRESS_JSON_LABEL);
        estimated_completion_time_ms=status_check.getInt(BobikConstants.ESTIMATED_TIME_REMAINING_TOKEN_LABEL);
        listener.onProgress(progress);
        if (progress == 1.0)         fetchScrapedData();
        return progress;
      }
 catch (      Exception e) {
        e.printStackTrace();
        throw new BobikException(e);
      }
    }
    protected void fetchScrapedData() throws BobikException {
      try {
        JSONObject job_data=callAPI(getStatusRequestObj(true),"String_Node_Str");
        processErrors(job_data,listener);
        scraped_data=job_data.getJSONObject(BobikConstants.RESULTS_TOKEN_LABEL);
      }
 catch (      Exception e) {
        e.printStackTrace();
        throw new BobikException(e);
      }
      listener.onSuccess(scraped_data);
    }
    @Override public boolean cancel(    boolean b){
      try {
        String url="String_Node_Str" + id() + "String_Node_Str";
        doHttp(url,"String_Node_Str",new JSONObject());
      }
 catch (      Exception e) {
        e.printStackTrace();
      }
      cancelled=true;
      return true;
    }
    @Override public boolean isCancelled(){
      return cancelled;
    }
    @Override public boolean isDone(){
      try {
        return cancelled || scraped_data != null || getProgress() == 1.0;
      }
 catch (      BobikException e) {
        e.printStackTrace();
        return false;
      }
    }
    @Override public JSONObject get() throws InterruptedException, ExecutionException {
      try {
        waitForCompletion();
      }
 catch (      Exception e) {
        throw new ExecutionException(e);
      }
      return scraped_data;
    }
    @Override public JSONObject get(    long l,    TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException {
      return get();
    }
    private boolean checkTimer() throws BobikException {
      if (System.currentTimeMillis() - startTime > timeoutMs)       throw new BobikException("String_Node_Str" + timeoutMs + "String_Node_Str");
      return true;
    }
    @Override public void waitForCompletion() throws BobikException {
      if (job_waiter == null) {
        job_waiter=runners.submit(new Callable<Object>(){
          @Override public Object call() throws Exception {
            while (checkTimer() && getProgress() != 1.0) {
              try {
                Thread.sleep(estimated_completion_time_ms);
              }
 catch (              InterruptedException e) {
                e.printStackTrace();
                new BobikException(e);
              }
            }
            return null;
          }
        }
);
      }
      try {
        job_waiter.get();
      }
 catch (      Exception e) {
        e.printStackTrace();
        new BobikException(e);
      }
    }
  }
;
  listener.init(job);
  processErrors(job_submission,listener);
  return job;
}

Fixed version (ground truth):
/** 
 * Kicks off an asynchronous scraping job and returns a proxy object. This proxy is only for added convenience of monitoring/cancelling the job. The listener you pass as a parameter does all this and more already.
 * @param request The scraping request, built in accordance with http://usebobik.com/api/docs#func_ref
 * @param listener An object encapsulating various useful callbacks
 * @return proxy to monitor/abort the scraping job
 * @throws BobikException thrown on all Bobik-specific errors
 * @throws IOException thrown on network problems
 * @throws JSONException not common, thrown on surprise JSON parsing errors
 * @throws ExecutionException not common, thrown if there's a client-level error during the scheduling of threads
 * @throws InterruptedException not common, thrown if there's a client-level error during the scheduling of threads
 */
public Job scrape(JSONObject request,final JobListener listener) throws BobikException, IOException, JSONException, ExecutionException, InterruptedException {
  JSONObject job_submission=callAPI(request,"String_Node_Str");
  processErrors(job_submission,listener);
  final long startTime=System.currentTimeMillis();
  final String job_id=getJobIdOrFail(job_submission);
  final Job job=new Job(){
    private JSONObject scraped_data=null;
    private Future<Object> job_waiter=null;
    private int estimated_completion_time_ms=-1;
    private boolean cancelled=false;
    private JSONObject getStatusRequestObj(    boolean download_results) throws BobikException, JSONException {
      JSONObject progress_check=new JSONObject();
      progress_check.accumulate(BobikConstants.JOB_TOKEN_LABEL,id());
      progress_check.accumulate(BobikConstants.SKIP_DATA_TOKEN_LABEL,!download_results);
      return progress_check;
    }
    @Override public String id(){
      return job_id;
    }
    @Override public float getProgress() throws BobikException {
      try {
        JSONObject status_check=callAPI(getStatusRequestObj(false),"String_Node_Str");
        processErrors(status_check,listener);
        float progress=(float)status_check.getDouble(BobikConstants.PROGRESS_JSON_LABEL);
        estimated_completion_time_ms=status_check.getInt(BobikConstants.ESTIMATED_TIME_REMAINING_TOKEN_LABEL);
        listener.onProgress(progress);
        if (progress == 1.0)         fetchScrapedData();
        return progress;
      }
 catch (      Exception e) {
        e.printStackTrace();
        throw new BobikException(e);
      }
    }
    protected void fetchScrapedData() throws BobikException {
      try {
        JSONObject job_data=callAPI(getStatusRequestObj(true),"String_Node_Str");
        processErrors(job_data,listener);
        scraped_data=job_data.getJSONObject(BobikConstants.RESULTS_TOKEN_LABEL);
      }
 catch (      Exception e) {
        e.printStackTrace();
        throw new BobikException(e);
      }
      listener.onSuccess(scraped_data);
    }
    @Override public boolean cancel(    boolean b){
      try {
        String url="String_Node_Str" + id() + "String_Node_Str";
        doHttp(url,"String_Node_Str",new JSONObject());
      }
 catch (      Exception e) {
        e.printStackTrace();
      }
      cancelled=true;
      return true;
    }
    @Override public boolean isCancelled(){
      return cancelled;
    }
    @Override public boolean isDone(){
      try {
        return cancelled || scraped_data != null || getProgress() == 1.0;
      }
 catch (      BobikException e) {
        e.printStackTrace();
        return false;
      }
    }
    @Override public JSONObject get() throws InterruptedException, ExecutionException {
      try {
        waitForCompletion();
      }
 catch (      Exception e) {
        throw new ExecutionException(e);
      }
      return scraped_data;
    }
    @Override public JSONObject get(    long l,    TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException {
      return get();
    }
    private boolean checkTimer() throws BobikException {
      if (System.currentTimeMillis() - startTime > timeoutMs)       throw new BobikException("String_Node_Str" + timeoutMs + "String_Node_Str");
      return true;
    }
    @Override public void waitForCompletion() throws BobikException {
      if (job_waiter == null) {
        job_waiter=runners.submit(new Callable<Object>(){
          @Override public Object call() throws Exception {
            while (checkTimer() && getProgress() != 1.0) {
              try {
                Thread.sleep(estimated_completion_time_ms);
              }
 catch (              InterruptedException e) {
                e.printStackTrace();
                new BobikException(e);
              }
            }
            return null;
          }
        }
);
      }
      try {
        job_waiter.get();
      }
 catch (      Exception e) {
        e.printStackTrace();
        new BobikException(e);
      }
    }
  }
;
  listener.init(job);
  processErrors(job_submission,listener);
  return job;
}