/**
  * Worker method called by the retry processing timer. This checks any reliable messages that have
  * not yet had an acknowledgement (or explicit error) to see if they need retrying, or if they are
  * due for expiry. Any expired messages have the expiry process, including any user-supplied
  * expiry handler, called on them.
  *
  * <p>It also requests that the listener checks its de-duplication list against persist durations,
  * and clears out any message ids from that list that are out of scope.
  */
 void processRetries() {
   if ((requests == null) || (requests.isEmpty())) {
     listener.cleanDeduplicationList();
     return;
   }
   Calendar check = Calendar.getInstance();
   ArrayList<Sendable> expires = new ArrayList<>();
   for (Sendable s : requests.values()) {
     Calendar expiryTime = s.getStarted();
     expiryTime.add(Calendar.SECOND, s.getPersistDuration());
     if (expiryTime.before(check)) {
       expires.add(s);
     } else {
       Calendar retryAfter = s.lastTry();
       if (retryAfter == null) return;
       retryAfter.add(Calendar.SECOND, s.getRetryInterval());
       if (retryAfter.before(check)) {
         (new Transmitter(s)).start();
       }
     }
   }
   for (Sendable s : expires) {
     try {
       removeRequest(s.getMessageId());
       s.expire();
     } catch (Exception e) {
       SpineToolsLogger.getInstance()
           .log("org.warlock.spine.connection.ConnectionManager.expireException", e);
     }
   }
 }
 private void depersist(String a) {
   try {
     File f = new File(messageDirectory, a);
     if (f.exists()) f.delete();
   } catch (Exception e) {
     SpineToolsLogger.getInstance()
         .log("org.warlock.spine.connection.ConnectionManager.depersistException", e);
   }
 }
 public void stopRetryProcessor() {
   if (timer == null) return;
   try {
     timer.shutdown();
   } catch (Exception e) {
     SpineToolsLogger.getInstance()
         .log("org.warlock.spine.connection.ConnectionManager.stopRetryProcessor", e);
   }
 }
 /**
  * Used for processing asynchronous acknowledgements. If the given message id is known (i.e. if we
  * have a request for it) then it is removed. Otherwise the unknown id is logged. This is only
  * called by the TMS listener at present, though in principle it could be called for other
  * transports.
  *
  * @param a ebXml message id of the received acknowledgement or error notification
  */
 public void registerAck(String a) {
   if (a == null) return;
   if (requests.containsKey(a)) {
     requests.remove(a);
     depersist(a);
   } else {
     SpineToolsLogger.getInstance()
         .log(
             "org.warlock.spine.connection.ConnectionManager.registerAck",
             "Ack received for unrecognised message id");
   }
 }