All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javapns.feedback.FeedbackServiceManager Maven / Gradle / Ivy

The newest version!
package javapns.feedback;

import javapns.communication.exceptions.CommunicationException;
import javapns.communication.exceptions.KeystoreException;
import javapns.devices.Device;
import javapns.devices.DeviceFactory;
import javapns.devices.implementations.basic.BasicDevice;
import javapns.devices.implementations.basic.BasicDeviceFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLSocket;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Timestamp;
import java.util.LinkedList;
import java.util.List;

/**
 * Class for interacting with a specific Feedback Service.
 *
 * @author kljajo, dgardon, Sylvain Pedneault
 */
public class FeedbackServiceManager {

  private static final Logger logger = LoggerFactory.getLogger(FeedbackServiceManager.class);

  /* Length of the tuple sent by Apple */
  private static final int FEEDBACK_TUPLE_SIZE = 38;

  @Deprecated
  private DeviceFactory deviceFactory;

  /**
   * Constructs a FeedbackServiceManager with a supplied DeviceFactory.
   *
   * @deprecated The DeviceFactory-based architecture is deprecated.
   */
  @Deprecated
  private FeedbackServiceManager(final DeviceFactory deviceFactory) {
    this.setDeviceFactory(deviceFactory);
  }

  /**
   * Constructs a FeedbackServiceManager with a default basic DeviceFactory.
   */
  @SuppressWarnings("deprecation")
  public FeedbackServiceManager() {
    this.setDeviceFactory(new BasicDeviceFactory());
  }

  /**
   * Retrieve all devices which have un-installed the application w/Path to keystore
   *
   * @param server Connection information for the Apple server
   * @return List of Devices
   * @throws IOException
   * @throws FileNotFoundException
   * @throws CertificateException
   * @throws NoSuchAlgorithmException
   * @throws KeyStoreException
   * @throws KeyManagementException
   * @throws UnrecoverableKeyException
   */
  /**
   * @throws KeystoreException
   * @throws CommunicationException
   */
  public List getDevices(final AppleFeedbackServer server) throws KeystoreException, CommunicationException {
    final ConnectionToFeedbackServer connectionHelper = new ConnectionToFeedbackServer(server);
    final SSLSocket socket = connectionHelper.getSSLSocket();
    return getDevices(socket);
  }

  /**
   * Retrieves the list of devices from an established SSLSocket.
   *
   * @param socket
   * @return Devices
   * @throws CommunicationException
   */
  private LinkedList getDevices(final SSLSocket socket) throws CommunicationException {

    // Compute
    LinkedList listDev;
      try (socket) {
          final InputStream socketStream = socket.getInputStream();

          // Read bytes
          final byte[] b = new byte[1024];
          final ByteArrayOutputStream message = new ByteArrayOutputStream();
          int nbBytes;
          // socketStream.available can return 0
          // http://forums.sun.com/thread.jspa?threadID=5428561
          while ((nbBytes = socketStream.read(b, 0, 1024)) != -1) {
              message.write(b, 0, nbBytes);
          }

          listDev = new LinkedList<>();
          final byte[] listOfDevices = message.toByteArray();
          final int nbTuples = listOfDevices.length / FEEDBACK_TUPLE_SIZE;
        logger.debug("Found: [{}]", nbTuples);
          for (int i = 0; i < nbTuples; i++) {
              final int offset = i * FEEDBACK_TUPLE_SIZE;

              // Build date
              final int firstByte;
              final int secondByte;
              final int thirdByte;
              final int fourthByte;
              final long anUnsignedInt;

              firstByte = 0x000000FF & ((int) listOfDevices[offset]);
              secondByte = 0x000000FF & ((int) listOfDevices[offset + 1]);
              thirdByte = 0x000000FF & ((int) listOfDevices[offset + 2]);
              fourthByte = 0x000000FF & ((int) listOfDevices[offset + 3]);
              anUnsignedInt = ((long) (firstByte << 24 | secondByte << 16 | thirdByte << 8 | fourthByte)) & 0xFFFFFFFFL;
              final Timestamp timestamp = new Timestamp(anUnsignedInt * 1000);

              // Build device token length
              final int deviceTokenLength = listOfDevices[offset + 4] << 8 | listOfDevices[offset + 5];

              // Build device token
              String deviceToken = "";
              int octet;
              for (int j = 0; j < 32; j++) {
                  octet = 0x000000FF & ((int) listOfDevices[offset + 6 + j]);
                  deviceToken = deviceToken.concat(String.format("%02x", octet));
              }

              // Build device and add to list
              /* Create a basic device, as we do not want to go through the factory and create a device in the actual database... */
              final Device device = new BasicDevice();
              device.setToken(deviceToken);
              device.setLastRegister(timestamp);
              listDev.add(device);
            logger.info("FeedbackManager retrieves one device :  {};{};{}.", timestamp, deviceTokenLength, deviceToken);
          }

          // Close the socket and return the list

      } catch (final Exception e) {
          logger.debug("Caught exception fetching devices from Feedback Service");
          throw new CommunicationException("Problem communicating with Feedback service", e);
      }
      // empty
      return listDev;
  }

  /**
   * @return a device factory
   * @deprecated The DeviceFactory-based architecture is deprecated.
   */
  @Deprecated
  public DeviceFactory getDeviceFactory() {
    return deviceFactory;
  }

  /**
   * @param deviceFactory
   * @deprecated The DeviceFactory-based architecture is deprecated.
   */
  @Deprecated
  private void setDeviceFactory(final DeviceFactory deviceFactory) {
    this.deviceFactory = deviceFactory;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy