@Test
  public void testSendingUpdate() throws Exception {
    // fill the model with data
    SignalKModel model = SignalKModelFactory.getMotuTestInstance();

    // model = Util.populateModel(model, new
    // File("src/test/resources/samples/basicModel.txt"));

    // create STOMP connection
    StompConnection connection = new StompConnection();
    connection.open("localhost", 61613);
    logger.debug("Opened STOMP socket, connecting.. ");
    StompFrame connect = connection.connect("system", "manager");
    // StompFrame connect = connection.receive();
    if (!connect.getAction().equals(Stomp.Responses.CONNECTED)) {
      throw new Exception("Not connected");
    }
    logger.debug("connected" + connect.getHeaders());

    HashMap<String, String> headers = new HashMap<String, String>();

    // headers.put(WebsocketConstants.CONNECTION_KEY, uuid);
    connection.send(
        "/queue/signalk.put",
        FileUtils.readFileToString(
            new File("src/test/resources/samples/windAngleUpdate.json.txt")));
    latch.await(2, TimeUnit.SECONDS);
    assertEquals(338.0, model.getValue(vessels_dot_self_dot + env_wind_angleApparent));
    assertEquals(6.8986404, model.getValue(vessels_dot_self_dot + env_wind_speedApparent));
    // disconnect
    connection.disconnect();
  }
 public ActiveMQMessage convertFrame(StompProtocolConverter converter, StompFrame command)
     throws JMSException, ProtocolException {
   final Map<?, ?> headers = command.getHeaders();
   final ActiveMQMessage msg;
   /*
    * To reduce the complexity of this method perhaps a Chain of Responsibility
    * would be a better implementation
    */
   if (headers.containsKey(Stomp.Headers.AMQ_MESSAGE_TYPE)) {
     String intendedType = (String) headers.get(Stomp.Headers.AMQ_MESSAGE_TYPE);
     if (intendedType.equalsIgnoreCase("text")) {
       ActiveMQTextMessage text = new ActiveMQTextMessage();
       try {
         ByteArrayOutputStream bytes = new ByteArrayOutputStream(command.getContent().length + 4);
         DataOutputStream data = new DataOutputStream(bytes);
         data.writeInt(command.getContent().length);
         data.write(command.getContent());
         text.setContent(bytes.toByteSequence());
         data.close();
       } catch (Throwable e) {
         throw new ProtocolException("Text could not bet set: " + e, false, e);
       }
       msg = text;
     } else if (intendedType.equalsIgnoreCase("bytes")) {
       ActiveMQBytesMessage byteMessage = new ActiveMQBytesMessage();
       byteMessage.writeBytes(command.getContent());
       msg = byteMessage;
     } else {
       throw new ProtocolException("Unsupported message type '" + intendedType + "'", false);
     }
   } else if (headers.containsKey(Stomp.Headers.CONTENT_LENGTH)) {
     headers.remove(Stomp.Headers.CONTENT_LENGTH);
     ActiveMQBytesMessage bm = new ActiveMQBytesMessage();
     bm.writeBytes(command.getContent());
     msg = bm;
   } else {
     ActiveMQTextMessage text = new ActiveMQTextMessage();
     try {
       ByteArrayOutputStream bytes = new ByteArrayOutputStream(command.getContent().length + 4);
       DataOutputStream data = new DataOutputStream(bytes);
       data.writeInt(command.getContent().length);
       data.write(command.getContent());
       text.setContent(bytes.toByteSequence());
       data.close();
     } catch (Throwable e) {
       throw new ProtocolException("Text could not bet set: " + e, false, e);
     }
     msg = text;
   }
   Helper.copyStandardHeadersFromFrameToMessage(converter, command, msg, this);
   return msg;
 }
  @Override
  public ActiveMQMessage convertFrame(ProtocolConverter converter, StompFrame command)
      throws JMSException, ProtocolException {
    Map<String, String> headers = command.getHeaders();
    ActiveMQMessage msg;
    String transformation = headers.get(Headers.TRANSFORMATION);
    if (headers.containsKey(Headers.CONTENT_LENGTH)
        || transformation.equals(Transformations.JMS_BYTE.toString())) {
      msg = super.convertFrame(converter, command);
    } else {
      HierarchicalStreamReader in;

      try {
        String text = new String(command.getContent(), "UTF-8");
        switch (Transformations.getValue(transformation)) {
          case JMS_OBJECT_XML:
            in = new XppReader(new StringReader(text), XppFactory.createDefaultParser());
            msg = createObjectMessage(in);
            break;
          case JMS_OBJECT_JSON:
            in = new JettisonMappedXmlDriver().createReader(new StringReader(text));
            msg = createObjectMessage(in);
            break;
          case JMS_MAP_XML:
            in = new XppReader(new StringReader(text), XppFactory.createDefaultParser());
            msg = createMapMessage(in);
            break;
          case JMS_MAP_JSON:
            in = new JettisonMappedXmlDriver().createReader(new StringReader(text));
            msg = createMapMessage(in);
            break;
          default:
            throw new Exception("Unkown transformation: " + transformation);
        }
      } catch (Throwable e) {
        command.getHeaders().put(Headers.TRANSFORMATION_ERROR, e.getMessage());
        msg = super.convertFrame(converter, command);
      }
    }

    copyStandardHeadersFromFrameToMessage(converter, command, msg, this);
    return msg;
  }
  @Test
  public void testSubscribe() throws Exception {
    // fill the model with data
    SignalKModel model = SignalKModelFactory.getMotuTestInstance();
    model.putAll(TestHelper.getBasicModel().getFullData());

    // create STOMP connection
    StompConnection connection = new StompConnection();
    connection.open("localhost", 61613);
    logger.debug("Opened STOMP socket, connecting.. ");
    StompFrame connect = connection.connect("system", "manager");
    // StompFrame connect = connection.receive();
    if (!connect.getAction().equals(Stomp.Responses.CONNECTED)) {
      throw new Exception("Not connected");
    }
    logger.debug("connected" + connect.getHeaders());

    // create a private receive queue
    String uuid = UUID.randomUUID().toString();
    connection.subscribe(
        "/queue/signalk." + uuid + ".vessels.motu.navigation", Subscribe.AckModeValues.AUTO);

    // subscribe
    Json subMsg =
        getSubscribe(
            "vessels." + SignalKConstants.self, "navigation", 1000, 0, FORMAT_DELTA, POLICY_FIXED);
    subMsg.set(
        nz.co.fortytwo.signalk.util.ConfigConstants.OUTPUT_TYPE,
        nz.co.fortytwo.signalk.util.ConfigConstants.OUTPUT_STOMP);
    subMsg.set(WebsocketConstants.CONNECTION_KEY, uuid);
    HashMap<String, String> headers = new HashMap<String, String>();

    // queue>signalk.3202a939-1681-4a74-ad4b-3a90212e4f33.vessels.motu.navigation
    // set private queue to receive data
    headers.put("reply-to", "/queue/signalk." + uuid + ".vessels.motu.navigation");
    headers.put(WebsocketConstants.CONNECTION_KEY, uuid);
    connection.send("/queue/signalk.put", subMsg.toString(), null, headers);

    // listen for messages
    StompFrame message = connection.receive();
    logger.debug("Body: " + message.getBody());
    assertNotNull(message);
    Json reply = Json.read(message.getBody());

    assertNotNull(reply.at(SignalKConstants.CONTEXT));
    assertNotNull(reply.at(SignalKConstants.UPDATES));
    // unsubscribe
    subMsg =
        getSubscribe(
            "vessels." + SignalKConstants.self, "navigation", 1000, 0, FORMAT_DELTA, POLICY_FIXED);
    connection.send("/queue/signalk.subscribe", subMsg.toString(), null, headers);
    connection.unsubscribe("/queue/signalk." + uuid + ".vessels.motu.navigation");
    // disconnect
    connection.disconnect();
  }
  @Test
  public void testSendingGetFull() throws Exception {
    // fill the model with data
    SignalKModel model = SignalKModelFactory.getMotuTestInstance();
    model.putAll(TestHelper.getBasicModel().getFullData());

    // create STOMP connection
    StompConnection connection = new StompConnection();
    connection.open("localhost", 61613);
    logger.debug("Opened STOMP socket, connecting.. ");
    StompFrame connect = connection.connect("system", "manager");
    // StompFrame connect = connection.receive();
    if (!connect.getAction().equals(Stomp.Responses.CONNECTED)) {
      throw new Exception("Not connected");
    }
    logger.debug("connected" + connect.getHeaders());

    // create a private receive queue
    String uuid = UUID.randomUUID().toString();
    connection.subscribe(
        "/queue/signalk." + uuid + "." + vessels_dot_self_dot + env_wind,
        Subscribe.AckModeValues.AUTO);
    latch.await(2, TimeUnit.SECONDS);
    // send list
    Json subMsg =
        getGet("vessels." + SignalKConstants.self, env_wind + ".*", SignalKConstants.FORMAT_FULL);
    HashMap<String, String> headers = new HashMap<String, String>();
    logger.debug("sending" + subMsg);
    // queue>signalk.3202a939-1681-4a74-ad4b-3a90212e4f33.vessels.motu.navigation
    // set private queue to receive data
    headers.put("reply-to", "/queue/signalk." + uuid + dot + vessels_dot_self_dot + env_wind);
    headers.put(WebsocketConstants.CONNECTION_KEY, uuid);
    connection.send("/queue/signalk.put", subMsg.toString(), null, headers);

    // listen for messages
    StompFrame message = connection.receive();
    logger.debug("Body: " + message.getBody());
    assertNotNull(message);
    Json reply = Json.read(message.getBody());

    assertNotNull(reply.at(SignalKConstants.vessels));
    assertNotNull(reply.at(SignalKConstants.vessels).at(SignalKConstants.self).at(env).at("wind"));
    // unsubscribe
    connection.unsubscribe("/queue/signalk." + uuid + "." + vessels_dot_self_dot + env_wind);
    // disconnect
    connection.disconnect();
  }
  public StompFrame convertMessage(StompProtocolConverter converter, ActiveMQMessage message)
      throws IOException, JMSException {
    StompFrame command = new StompFrame();
    command.setAction(Stomp.Responses.MESSAGE);
    Map<String, String> headers = new HashMap<>(25);
    command.setHeaders(headers);

    Helper.copyStandardHeadersFromMessageToFrame(converter, message, command, this);

    if (message.getDataStructureType() == ActiveMQTextMessage.DATA_STRUCTURE_TYPE) {

      if (!message.isCompressed() && message.getContent() != null) {
        ByteSequence msgContent = message.getContent();
        if (msgContent.getLength() > 4) {
          byte[] content = new byte[msgContent.getLength() - 4];
          System.arraycopy(msgContent.data, 4, content, 0, content.length);
          command.setContent(content);
        }
      } else {
        ActiveMQTextMessage msg = (ActiveMQTextMessage) message.copy();
        String messageText = msg.getText();
        if (messageText != null) {
          command.setContent(msg.getText().getBytes("UTF-8"));
        }
      }

    } else if (message.getDataStructureType() == ActiveMQBytesMessage.DATA_STRUCTURE_TYPE) {

      ActiveMQBytesMessage msg = (ActiveMQBytesMessage) message.copy();
      msg.setReadOnlyBody(true);
      byte[] data = new byte[(int) msg.getBodyLength()];
      msg.readBytes(data);

      headers.put(Stomp.Headers.CONTENT_LENGTH, Integer.toString(data.length));
      command.setContent(data);
    }

    return command;
  }
 public synchronized void sendFrame(StompFrame frame) throws Exception {
   checkConnected();
   connection.getRemote().sendString(frame.format());
 }
  @Override
  public StompFrame convertMessage(ProtocolConverter converter, ActiveMQMessage message)
      throws IOException, JMSException {

    StompFrame command = new StompFrame();
    command.setAction(Responses.MESSAGE);
    Map<String, String> headers = new HashMap<String, String>(25);
    command.setHeaders(headers);

    copyStandardHeadersFromMessageToFrame(converter, message, command, this);

    String transformation = headers.get(Headers.TRANSFORMATION);

    if (message.getDataStructureType() == ActiveMQObjectMessage.DATA_STRUCTURE_TYPE) {

      if (Transformations.JMS_XML.equals(transformation)) {
        headers.put(Headers.TRANSFORMATION, Transformations.JMS_OBJECT_XML.toString());
      } else if (Transformations.JMS_JSON.equals(transformation)) {
        headers.put(Headers.TRANSFORMATION, Transformations.JMS_OBJECT_JSON.toString());
      }

      if (!headers.containsKey(Headers.TRANSFORMATION)) {
        headers.put(Headers.TRANSFORMATION, Transformations.JMS_OBJECT_XML.toString());
      }

      ActiveMQObjectMessage msg = (ActiveMQObjectMessage) message.copy();
      command.setContent(
          marshall(msg.getObject(), headers.get(Headers.TRANSFORMATION)).getBytes("UTF-8"));

    } else if (message.getDataStructureType() == ActiveMQMapMessage.DATA_STRUCTURE_TYPE) {

      if (Transformations.JMS_XML.equals(transformation)) {
        headers.put(Headers.TRANSFORMATION, Transformations.JMS_MAP_XML.toString());
      } else if (Transformations.JMS_JSON.equals(transformation)) {
        headers.put(Headers.TRANSFORMATION, Transformations.JMS_MAP_JSON.toString());
      }

      if (!headers.containsKey(Headers.TRANSFORMATION)) {
        headers.put(Headers.TRANSFORMATION, Transformations.JMS_MAP_XML.toString());
      }

      ActiveMQMapMessage msg = (ActiveMQMapMessage) message.copy();
      command.setContent(
          marshall((Serializable) msg.getContentMap(), headers.get(Headers.TRANSFORMATION))
              .getBytes("UTF-8"));

    } else if (message.getDataStructureType() == ActiveMQMessage.DATA_STRUCTURE_TYPE
        && AdvisorySupport.ADIVSORY_MESSAGE_TYPE.equals(message.getType())) {

      if (Transformations.JMS_XML.equals(transformation)) {
        headers.put(Headers.TRANSFORMATION, Transformations.JMS_ADVISORY_XML.toString());
      } else if (Transformations.JMS_JSON.equals(transformation)) {
        headers.put(Headers.TRANSFORMATION, Transformations.JMS_ADVISORY_JSON.toString());
      }

      if (!headers.containsKey(Headers.TRANSFORMATION)) {
        headers.put(Headers.TRANSFORMATION, Transformations.JMS_ADVISORY_JSON.toString());
      }

      String body =
          marshallAdvisory(message.getDataStructure(), headers.get(Headers.TRANSFORMATION));
      command.setContent(body.getBytes("UTF-8"));

    } else {
      command = super.convertMessage(converter, message);
    }

    return command;
  }