private void completeWithMissingParams(JobDataMap jobDataMap, JobDataMap previousJobDataMap) {
   for (Iterator<Entry<String, Object>> iterator = previousJobDataMap.entrySet().iterator();
       iterator.hasNext(); ) {
     Entry<String, Object> entryFromPrevious = (Entry<String, Object>) iterator.next();
     if (!jobDataMap.containsKey(entryFromPrevious.getKey())) {
       if (!FOR_EACH_LISTENER.equals(entryFromPrevious.getKey())) {
         jobDataMap.put(entryFromPrevious.getKey(), entryFromPrevious.getValue());
       }
     }
   }
 }
  /** @see org.quartz.Job#execute(org.quartz.JobExecutionContext) */
  public void execute(JobExecutionContext context) throws JobExecutionException {
    JobDataMap mergedJobDataMap = context.getMergedJobDataMap();
    SchedulerContext schedCtxt = null;
    try {
      schedCtxt = context.getScheduler().getContext();
    } catch (SchedulerException e) {
      throw new JobExecutionException("Error obtaining scheduler context.", e, false);
    }

    String fileName = mergedJobDataMap.getString(FILE_NAME);
    String listenerName = mergedJobDataMap.getString(FILE_SCAN_LISTENER_NAME);

    if (fileName == null) {
      throw new JobExecutionException(
          "Required parameter '" + FILE_NAME + "' not found in merged JobDataMap");
    }
    if (listenerName == null) {
      throw new JobExecutionException(
          "Required parameter '" + FILE_SCAN_LISTENER_NAME + "' not found in merged JobDataMap");
    }

    FileScanListener listener = (FileScanListener) schedCtxt.get(listenerName);

    if (listener == null) {
      throw new JobExecutionException(
          "FileScanListener named '" + listenerName + "' not found in SchedulerContext");
    }

    long lastDate = -1;
    if (mergedJobDataMap.containsKey(LAST_MODIFIED_TIME)) {
      lastDate = mergedJobDataMap.getLong(LAST_MODIFIED_TIME);
    }

    long newDate = getLastModifiedDate(fileName);

    if (newDate < 0) {
      log.warn("File '" + fileName + "' does not exist.");
      return;
    }

    if (lastDate > 0 && (newDate != lastDate)) {
      // notify call back...
      log.info("File '" + fileName + "' updated, notifying listener.");
      listener.fileUpdated(fileName);
    } else if (log.isDebugEnabled()) {
      log.debug("File '" + fileName + "' unchanged.");
    }

    // It is the JobDataMap on the JobDetail which is actually stateful
    context.getJobDetail().getJobDataMap().put(LAST_MODIFIED_TIME, newDate);
  }