/**
   * Sends APNs notifications ({@link UnifiedPushMessage}) to all devices, that are represented by
   * the {@link Collection} of tokens for the given {@link iOSVariant}.
   *
   * @param iOSVariant the logical construct, needed to lookup the certificate and the passphrase.
   * @param tokens collection of tokens, representing actual iOS devices
   * @param pushMessage the payload to be submitted
   */
  public void sendPushMessage(
      iOSVariant iOSVariant, Collection<String> tokens, UnifiedPushMessage pushMessage) {
    // no need to send empty list
    if (tokens.isEmpty()) {
      return;
    }

    PayloadBuilder builder =
        APNS.newPayload()
            // adding recognized key values
            .alertBody(pushMessage.getAlert()) // alert dialog, in iOS
            .badge(pushMessage.getBadge()) // little badge icon update;
            .sound(pushMessage.getSound()); // sound to be played by app

    // apply the 'content-available:1' value:
    if (pushMessage.isContentAvailable()) {
      // content-available:1 is (with iOS7) not only used
      // Newsstand, however 'notnoop' names it this way (legacy)...
      builder = builder.forNewsstand();
    }

    builder = builder.customFields(pushMessage.getData()); // adding other (submitted) fields

    final String apnsMessage = builder.build(); // build the JSON payload, for APNs

    ApnsService service = buildApnsService(iOSVariant);

    if (service != null) {
      try {
        logger.fine(String.format("Sending transformed APNs payload: '%s' ", apnsMessage));
        // send:
        service.start();

        Date expireDate = createFutureDateBasedOnTTL(pushMessage.getTimeToLive());
        service.push(tokens, apnsMessage, expireDate);

        // after sending, let's ask for the inactive tokens:
        final Set<String> inactiveTokens = service.getInactiveDevices().keySet();

        // transform the tokens to be all lower-case:
        final Set<String> transformedTokens = lowerCaseAllTokens(inactiveTokens);

        // trigger asynchronous deletion:
        clientInstallationService.removeInstallationsForVariantByDeviceTokens(
            iOSVariant.getVariantID(), transformedTokens);
      } catch (RuntimeException e) {
        logger.log(Level.SEVERE, "Error sending messages to APN server", e);
      } finally {

        // tear down and release resources:
        service.stop();
      }
    } else {
      logger.severe("No certificate was found. Could not send messages to APNs");
    }
  }