mirror of https://github.com/apache/activemq.git
Merge pull request #1290 from cshannon/AMQ-8398-stomp-fix
AMQ-8398 - Fix Stomp to OpenWire UTF-8 translation
This commit is contained in:
commit
e1bcbb9f3e
|
@ -18,6 +18,7 @@ package org.apache.activemq.transport.stomp;
|
||||||
|
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -53,12 +54,9 @@ public class LegacyFrameTranslator implements FrameTranslator {
|
||||||
if(intendedType.equalsIgnoreCase("text")){
|
if(intendedType.equalsIgnoreCase("text")){
|
||||||
ActiveMQTextMessage text = new ActiveMQTextMessage();
|
ActiveMQTextMessage text = new ActiveMQTextMessage();
|
||||||
try {
|
try {
|
||||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream(command.getContent().length + 4);
|
// AMQ-8398 - get the original text back so we decode from standard UTF-8
|
||||||
DataOutputStream data = new DataOutputStream(bytes);
|
// and set on the message so it will re-encode using AMQ modified UTF-8
|
||||||
data.writeInt(command.getContent().length);
|
text.setText(command.getBody());
|
||||||
data.write(command.getContent());
|
|
||||||
text.setContent(bytes.toByteSequence());
|
|
||||||
data.close();
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
throw new ProtocolException("Text could not bet set: " + e, false, e);
|
throw new ProtocolException("Text could not bet set: " + e, false, e);
|
||||||
}
|
}
|
||||||
|
@ -78,12 +76,9 @@ public class LegacyFrameTranslator implements FrameTranslator {
|
||||||
} else {
|
} else {
|
||||||
ActiveMQTextMessage text = new ActiveMQTextMessage();
|
ActiveMQTextMessage text = new ActiveMQTextMessage();
|
||||||
try {
|
try {
|
||||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream(command.getContent().length + 4);
|
// AMQ-8398 - get the original text back so we decode from standard UTF-8
|
||||||
DataOutputStream data = new DataOutputStream(bytes);
|
// and set on the message so it will re-encode using AMQ modified UTF-8
|
||||||
data.writeInt(command.getContent().length);
|
text.setText(command.getBody());
|
||||||
data.write(command.getContent());
|
|
||||||
text.setContent(bytes.toByteSequence());
|
|
||||||
data.close();
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
throw new ProtocolException("Text could not bet set: " + e, false, e);
|
throw new ProtocolException("Text could not bet set: " + e, false, e);
|
||||||
}
|
}
|
||||||
|
@ -103,22 +98,13 @@ public class LegacyFrameTranslator implements FrameTranslator {
|
||||||
FrameTranslator.Helper.copyStandardHeadersFromMessageToFrame(converter, message, command, this);
|
FrameTranslator.Helper.copyStandardHeadersFromMessageToFrame(converter, message, command, this);
|
||||||
|
|
||||||
if (message.getDataStructureType() == ActiveMQTextMessage.DATA_STRUCTURE_TYPE) {
|
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();
|
ActiveMQTextMessage msg = (ActiveMQTextMessage)message.copy();
|
||||||
|
// AMQ-8398 - get the original text back so we decode from modified UTF-8
|
||||||
|
// and then we can re-encode using the standard JDK encoding
|
||||||
String messageText = msg.getText();
|
String messageText = msg.getText();
|
||||||
if (messageText != null) {
|
if (messageText != null) {
|
||||||
command.setContent(msg.getText().getBytes("UTF-8"));
|
command.setContent(msg.getText().getBytes(StandardCharsets.UTF_8));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
} else if (message.getDataStructureType() == ActiveMQBytesMessage.DATA_STRUCTURE_TYPE) {
|
} else if (message.getDataStructureType() == ActiveMQBytesMessage.DATA_STRUCTURE_TYPE) {
|
||||||
|
|
||||||
ActiveMQBytesMessage msg = (ActiveMQBytesMessage)message.copy();
|
ActiveMQBytesMessage msg = (ActiveMQBytesMessage)message.copy();
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.apache.activemq.transport.stomp;
|
package org.apache.activemq.transport.stomp;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -75,11 +76,7 @@ public class StompFrame implements Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getBody() {
|
public String getBody() {
|
||||||
try {
|
return new String(content, StandardCharsets.UTF_8);
|
||||||
return new String(content, "UTF-8");
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
return new String(content);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setContent(byte[] data) {
|
public void setContent(byte[] data) {
|
||||||
|
|
|
@ -219,6 +219,84 @@ public class StompTest extends StompTestSupport {
|
||||||
assertTrue(Math.abs(tnow - tmsg) < 1000);
|
assertTrue(Math.abs(tnow - tmsg) < 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that a string that requires 4 bytes to encode using standard
|
||||||
|
// UTF-8 does not break when sent by Stomp and received by JMS/OpenWire
|
||||||
|
// AMQ uses a modified UTF-8 encoding that only uses 3 bytes so conversion
|
||||||
|
// needs to happen so this works.
|
||||||
|
@Test(timeout = 60000)
|
||||||
|
public void testSend4ByteUtf8StompToJms() throws Exception {
|
||||||
|
// Create test string using emojis, requires 4 bytes with standard UTF-8
|
||||||
|
String body = "!®౩\uD83D\uDE42";
|
||||||
|
MessageConsumer consumer = session.createConsumer(queue);
|
||||||
|
|
||||||
|
String frame = "CONNECT\n" + "login:system\n" + "passcode:manager\n\n" + Stomp.NULL;
|
||||||
|
stompConnection.sendFrame(frame);
|
||||||
|
|
||||||
|
frame = stompConnection.receiveFrame();
|
||||||
|
assertTrue(frame.startsWith("CONNECTED"));
|
||||||
|
|
||||||
|
// publish message with string that requires 4-byte UTF-8 encoding
|
||||||
|
frame = "SEND\n" + "destination:/queue/" + getQueueName() + "\n\n" + body + Stomp.NULL;
|
||||||
|
stompConnection.sendFrame(frame);
|
||||||
|
|
||||||
|
// Verify received message is original sent string
|
||||||
|
TextMessage message = (TextMessage)consumer.receive(2500);
|
||||||
|
assertNotNull(message);
|
||||||
|
assertEquals(body, message.getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that a string that requires 4 bytes to encode using standard
|
||||||
|
// UTF-8 does not break when sent by JMS/OpenWire and received by Stomp
|
||||||
|
// AMQ uses a modified UTF-8 encoding that only uses 3 bytes so conversion
|
||||||
|
// needs to happen so this works.
|
||||||
|
@Test(timeout = 60000)
|
||||||
|
public void testSend4ByteUtf8JmsToStomp() throws Exception {
|
||||||
|
// Create test string using emojis, requires 4 bytes with standard UTF-8
|
||||||
|
String body = "!®౩\uD83D\uDE42";
|
||||||
|
MessageProducer producer = session.createProducer(queue);
|
||||||
|
|
||||||
|
String frame = "CONNECT\n" + "login:system\n" + "passcode:manager\n\n" + Stomp.NULL;
|
||||||
|
stompConnection.sendFrame(frame);
|
||||||
|
|
||||||
|
frame = stompConnection.receiveFrame();
|
||||||
|
assertTrue(frame.startsWith("CONNECTED"));
|
||||||
|
frame = "SUBSCRIBE\n" + "destination:/queue/" + getQueueName() + "\n" + "ack:auto\n\n" + Stomp.NULL;
|
||||||
|
stompConnection.sendFrame(frame);
|
||||||
|
|
||||||
|
// publish message with string that requires 4-byte UTF-8 encoding
|
||||||
|
producer.send(session.createTextMessage(body));
|
||||||
|
|
||||||
|
// Verify received message is original sent string
|
||||||
|
StompFrame message = stompConnection.receive();
|
||||||
|
assertNotNull(message);
|
||||||
|
assertEquals(body, message.getBody());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that a string that requires 4 bytes to encode using standard
|
||||||
|
// UTF-8 does not break when sent by Stomp and received by Stomp
|
||||||
|
@Test(timeout = 60000)
|
||||||
|
public void testSend4ByteUtf8StompToStomp() throws Exception {
|
||||||
|
// Create test string using emojis, requires 4 bytes with standard UTF-8
|
||||||
|
String body = "!®౩\uD83D\uDE42";
|
||||||
|
|
||||||
|
String frame = "CONNECT\n" + "login:system\n" + "passcode:manager\n\n" + Stomp.NULL;
|
||||||
|
stompConnection.sendFrame(frame);
|
||||||
|
|
||||||
|
// publish message with string that requires 4-byte UTF-8 encoding
|
||||||
|
frame = "SEND\n" + "destination:/queue/" + getQueueName() + "\n\n" + body + Stomp.NULL;
|
||||||
|
stompConnection.sendFrame(frame);
|
||||||
|
|
||||||
|
frame = stompConnection.receiveFrame();
|
||||||
|
assertTrue(frame.startsWith("CONNECTED"));
|
||||||
|
frame = "SUBSCRIBE\n" + "destination:/queue/" + getQueueName() + "\n" + "ack:auto\n\n" + Stomp.NULL;
|
||||||
|
stompConnection.sendFrame(frame);
|
||||||
|
|
||||||
|
// Verify received message is original sent string
|
||||||
|
StompFrame message = stompConnection.receive();
|
||||||
|
assertNotNull(message);
|
||||||
|
assertEquals(body, message.getBody());
|
||||||
|
}
|
||||||
|
|
||||||
@Test(timeout = 60000)
|
@Test(timeout = 60000)
|
||||||
public void testJMSXGroupIdCanBeSet() throws Exception {
|
public void testJMSXGroupIdCanBeSet() throws Exception {
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue