/** * Encodes the given payload and headers into a {@code byte[]}. * * @param headers the headers * @param payload the payload * @return the encoded message */ public byte[] encode(Map<String, Object> headers, byte[] payload) { Assert.notNull(headers, "'headers' is required"); Assert.notNull(payload, "'payload' is required"); try { ByteArrayOutputStream baos = new ByteArrayOutputStream(128 + payload.length); DataOutputStream output = new DataOutputStream(baos); if (SimpMessageType.HEARTBEAT.equals(SimpMessageHeaderAccessor.getMessageType(headers))) { logger.trace("Encoded heartbeat"); output.write(StompDecoder.HEARTBEAT_PAYLOAD); } else { StompCommand command = StompHeaderAccessor.getCommand(headers); Assert.notNull(command, "Missing STOMP command: " + headers); output.write(command.toString().getBytes(StompDecoder.UTF8_CHARSET)); output.write(LF); writeHeaders(command, headers, payload, output); output.write(LF); writeBody(payload, output); output.write((byte) 0); } return baos.toByteArray(); } catch (IOException e) { throw new StompConversionException( "Failed to encode STOMP frame, headers=" + headers + ".", e); } }
@Override public String getDetailedLogMessage(Object payload) { if (isHeartbeat()) { return "heart-beat in session " + getSessionId(); } StompCommand command = getCommand(); if (command == null) { return super.getDetailedLogMessage(payload); } StringBuilder sb = new StringBuilder(); sb.append(command.name()).append(" ").append(getNativeHeaders()).append(appendSession()); if (getUser() != null) { sb.append(", user=").append(getUser().getName()); } if (command.isBodyAllowed()) { sb.append(appendPayload(payload)); } return sb.toString(); }
private void writeHeaders( StompCommand command, Map<String, Object> headers, byte[] payload, DataOutputStream output) throws IOException { @SuppressWarnings("unchecked") Map<String, List<String>> nativeHeaders = (Map<String, List<String>>) headers.get(NativeMessageHeaderAccessor.NATIVE_HEADERS); if (logger.isTraceEnabled()) { logger.trace("Encoding STOMP " + command + ", headers=" + nativeHeaders + "."); } if (nativeHeaders == null) { return; } boolean shouldEscape = (command != StompCommand.CONNECT && command != StompCommand.CONNECTED); for (Entry<String, List<String>> entry : nativeHeaders.entrySet()) { byte[] key = encodeHeaderString(entry.getKey(), shouldEscape); List<String> values = entry.getValue(); if (StompHeaderAccessor.STOMP_PASSCODE_HEADER.equals(entry.getKey())) { values = Arrays.asList(StompHeaderAccessor.getPasscode(headers)); } for (String value : values) { output.write(key); output.write(COLON); output.write(encodeHeaderString(value, shouldEscape)); output.write(LF); } } if (command.requiresContentLength()) { int contentLength = payload.length; output.write("content-length:".getBytes(StompDecoder.UTF8_CHARSET)); output.write(Integer.toString(contentLength).getBytes(StompDecoder.UTF8_CHARSET)); output.write(LF); } }
/** A constructor for creating message headers from a parsed STOMP frame. */ StompHeaderAccessor(StompCommand command, Map<String, List<String>> externalSourceHeaders) { super(command.getMessageType(), externalSourceHeaders); setHeader(COMMAND_HEADER, command); updateSimpMessageHeadersFromStompHeaders(); }
/** Decode a single STOMP frame from the given {@code buffer} into a {@link Message}. */ private Message<byte[]> decodeMessage(ByteBuffer buffer, MultiValueMap<String, String> headers) { Message<byte[]> decodedMessage = null; skipLeadingEol(buffer); buffer.mark(); String command = readCommand(buffer); if (command.length() > 0) { StompHeaderAccessor headerAccessor = null; byte[] payload = null; if (buffer.remaining() > 0) { StompCommand stompCommand = StompCommand.valueOf(command); headerAccessor = StompHeaderAccessor.create(stompCommand); initHeaders(headerAccessor); readHeaders(buffer, headerAccessor); payload = readPayload(buffer, headerAccessor); } if (payload != null) { if ((payload.length > 0) && (!headerAccessor.getCommand().isBodyAllowed())) { throw new StompConversionException( headerAccessor.getCommand() + " shouldn't have a payload: length=" + payload.length + ", headers=" + headers); } headerAccessor.updateSimpMessageHeadersFromStompHeaders(); headerAccessor.setLeaveMutable(true); decodedMessage = MessageBuilder.createMessage(payload, headerAccessor.getMessageHeaders()); if (logger.isDebugEnabled()) { logger.debug("Decoded " + decodedMessage); } } else { if (logger.isTraceEnabled()) { logger.trace("Received incomplete frame. Resetting buffer."); } if (headers != null && headerAccessor != null) { String name = NativeMessageHeaderAccessor.NATIVE_HEADERS; @SuppressWarnings("unchecked") MultiValueMap<String, String> map = (MultiValueMap<String, String>) headerAccessor.getHeader(name); if (map != null) { headers.putAll(map); } } buffer.reset(); } } else { if (logger.isTraceEnabled()) { logger.trace("Decoded heartbeat"); } StompHeaderAccessor headerAccessor = StompHeaderAccessor.createForHeartbeat(); initHeaders(headerAccessor); headerAccessor.setLeaveMutable(true); decodedMessage = MessageBuilder.createMessage(HEARTBEAT_PAYLOAD, headerAccessor.getMessageHeaders()); } return decodedMessage; }