@Override
 public void auditCrashed(Audit audit, Exception exception) {
   String url = "";
   if (audit.getSubject() != null) {
     url = audit.getSubject().getURL();
   }
   LOGGER.error(
       "AUDIT CRASHED:"
           + audit
           + ","
           + url
           + ","
           + (long) (audit.getDateOfCreation().getTime() / 1000),
       exception);
   Audit auditCrashed = null;
   for (Audit auditRunning : this.auditExecutionList.keySet()) {
     if (auditRunning.getId().equals(audit.getId())
         && (long) (auditRunning.getDateOfCreation().getTime() / 1000)
             == (long) (audit.getDateOfCreation().getTime() / 1000)) {
       auditCrashed = auditRunning;
       break;
     }
   }
   if (auditCrashed != null) {
     Long token = this.auditExecutionList.get(auditCrashed);
     this.auditExecutionList.remove(auditCrashed);
     this.auditCrashedList.put(token, new AbstractMap.SimpleImmutableEntry<>(audit, exception));
     this.exception = exception;
   }
 }
 @Override
 public void auditCompleted(Audit audit) {
   LOGGER.debug(
       "AUDIT COMPLETED:"
           + audit
           + ","
           + audit.getSubject().getURL()
           + ","
           + (long) (audit.getDateOfCreation().getTime() / 1000)
           + audit.getId());
   Audit auditCompleted = null;
   for (Audit auditRunning : this.auditExecutionList.keySet()) {
     if (auditRunning.getId().equals(audit.getId())
         && (long) (auditRunning.getDateOfCreation().getTime() / 1000)
             == (long) (audit.getDateOfCreation().getTime() / 1000)) {
       auditCompleted = auditRunning;
       break;
     }
   }
   if (auditCompleted != null) {
     Long token = this.auditExecutionList.get(auditCompleted);
     this.auditExecutionList.remove(auditCompleted);
     this.auditCompletedList.put(token, audit);
   }
 }
 protected Audit waitForAuditToComplete(Audit audit) {
   LOGGER.debug(
       "WAIT FOR AUDIT TO COMPLETE:"
           + audit
           + ","
           + (long) (audit.getDateOfCreation().getTime() / 1000));
   Long token = new Date().getTime();
   this.getAuditExecutionList().put(audit, token);
   // while the audit is not seen as completed or crashed
   while (!this.getAuditCompletedList().containsKey(token)
       && !this.getAuditCrashedList().containsKey(token)) {
     try {
       Thread.sleep(500);
     } catch (InterruptedException ex) {
       LOGGER.error("", ex);
     }
   }
   if ((audit = this.getAuditCompletedList().get(token)) != null) {
     this.getAuditCompletedList().remove(token);
     return audit;
   }
   if ((audit = this.getAuditCrashedList().get(token).getKey()) != null) {
     this.getAuditCrashedList().remove(token);
     return audit;
   }
   return null;
 }
 protected void onActTerminated(Act act, Audit audit) {
   this.audit = audit;
   Date endDate = new Date();
   act.setEndDate(endDate);
   if (audit.getStatus().equals(AuditStatus.COMPLETED)) {
     act.setStatus(ActStatus.COMPLETED);
   } else {
     act.setStatus(ActStatus.ERROR);
   }
   act = actDataService.saveOrUpdate(act);
   if (exception != null) {
     sendKrashAuditEmail(act, locale, exception);
     actDataService.delete(act.getId());
     auditDataService.delete(audit.getId());
     this.audit = null;
   }
 }