diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpMessagingTemplate.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpMessagingTemplate.java index 91594488fd..3bdf069777 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpMessagingTemplate.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/SimpMessagingTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,10 +26,17 @@ import org.springframework.messaging.core.AbstractMessageSendingTemplate; import org.springframework.messaging.core.MessagePostProcessor; import org.springframework.messaging.support.MessageBuilder; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** - * A specialization of {@link AbstractMessageSendingTemplate} that adds String-based - * destinations as a message header. + * A specialization of {@link AbstractMessageSendingTemplate} that interprets a + * String-based destination as the + * {@link org.springframework.messaging.simp.SimpMessageHeaderAccessor#DESTINATION_HEADER DESTINATION_HEADER} + * to be added to the headers of sent messages. + *

+ * Also provides methods for sending messages to a user. See + * {@link org.springframework.messaging.simp.user.UserDestinationResolver UserDestinationResolver} + * for more on user destinations. * * @author Rossen Stoyanchev * @since 4.0 @@ -127,30 +134,29 @@ public class SimpMessagingTemplate extends AbstractMessageSendingTemplate headers) throws MessagingException { - MessagePostProcessor postProcessor = null; - this.convertAndSendToUser(user, destination, payload, headers, postProcessor); + this.convertAndSendToUser(user, destination, payload, headers, null); } @Override public void convertAndSendToUser(String user, String destination, Object payload, MessagePostProcessor postProcessor) throws MessagingException { - Map headers = null; - this.convertAndSendToUser(user, destination, payload, headers, postProcessor); + this.convertAndSendToUser(user, destination, payload, null, postProcessor); } @Override public void convertAndSendToUser(String user, String destination, Object payload, Map headers, MessagePostProcessor postProcessor) throws MessagingException { + Assert.notNull(user, "User must not be null"); + user = StringUtils.replace(user, "/", "%2F"); super.convertAndSend(this.userDestinationPrefix + user + destination, payload, headers, postProcessor); } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/user/DefaultUserDestinationResolver.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/user/DefaultUserDestinationResolver.java index 0505acf203..60a8e39f33 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/user/DefaultUserDestinationResolver.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/user/DefaultUserDestinationResolver.java @@ -22,6 +22,7 @@ import org.springframework.messaging.Message; import org.springframework.messaging.simp.SimpMessageHeaderAccessor; import org.springframework.messaging.simp.SimpMessageType; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; import java.security.Principal; import java.util.Collections; @@ -138,6 +139,7 @@ public class DefaultUserDestinationResolver implements UserDestinationResolver { int endIndex = destination.indexOf('/', startIndex); Assert.isTrue(endIndex > 0, "Expected destination pattern \"/principal/{userId}/**\""); targetUser = destination.substring(startIndex, endIndex); + targetUser = StringUtils.replace(targetUser, "%2F", "/"); targetDestination = destination.substring(endIndex); targetSessionIds = this.userSessionRegistry.getSessionIds(targetUser); } diff --git a/spring-messaging/src/test/java/org/springframework/messaging/simp/SimpMessagingTemplateTests.java b/spring-messaging/src/test/java/org/springframework/messaging/simp/SimpMessagingTemplateTests.java new file mode 100644 index 0000000000..a5ab0c7331 --- /dev/null +++ b/spring-messaging/src/test/java/org/springframework/messaging/simp/SimpMessagingTemplateTests.java @@ -0,0 +1,72 @@ +/* + * Copyright 2002-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.messaging.simp; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.messaging.Message; +import org.springframework.messaging.StubMessageChannel; + +import java.util.List; + +import static org.junit.Assert.assertEquals; + +/** + * Unit tests for {@link org.springframework.messaging.simp.SimpMessagingTemplate}. + * + * @author Rossen Stoyanchev + */ +public class SimpMessagingTemplateTests { + + private SimpMessagingTemplate messagingTemplate; + + private StubMessageChannel messageChannel; + + + @Before + public void setup() { + this.messageChannel = new StubMessageChannel(); + this.messagingTemplate = new SimpMessagingTemplate(messageChannel); + } + + @Test + public void convertAndSendToUser() { + this.messagingTemplate.convertAndSendToUser("joe", "/queue/foo", "data"); + List> messages = this.messageChannel.getMessages(); + + assertEquals(1, messages.size()); + + Message message = messages.get(0); + SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.wrap(message); + + assertEquals(SimpMessageType.MESSAGE, headers.getMessageType()); + assertEquals("/user/joe/queue/foo", headers.getDestination()); + } + + @Test + public void convertAndSendToUserWithEncoding() { + this.messagingTemplate.convertAndSendToUser("http://joe.openid.example.org/", "/queue/foo", "data"); + List> messages = this.messageChannel.getMessages(); + + assertEquals(1, messages.size()); + + Message message = messages.get(0); + SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.wrap(message); + assertEquals("/user/http:%2F%2Fjoe.openid.example.org%2F/queue/foo", headers.getDestination()); + } + +} diff --git a/spring-messaging/src/test/java/org/springframework/messaging/simp/user/DefaultUserDestinationResolverTests.java b/spring-messaging/src/test/java/org/springframework/messaging/simp/user/DefaultUserDestinationResolverTests.java index a72aae58c4..959cefccfe 100644 --- a/spring-messaging/src/test/java/org/springframework/messaging/simp/user/DefaultUserDestinationResolverTests.java +++ b/spring-messaging/src/test/java/org/springframework/messaging/simp/user/DefaultUserDestinationResolverTests.java @@ -23,6 +23,7 @@ import org.springframework.messaging.simp.SimpMessageHeaderAccessor; import org.springframework.messaging.simp.SimpMessageType; import org.springframework.messaging.simp.TestPrincipal; import org.springframework.messaging.support.MessageBuilder; +import org.springframework.util.StringUtils; import java.util.Set; @@ -30,6 +31,8 @@ import static org.junit.Assert.assertEquals; /** * Unit tests for {@link org.springframework.messaging.simp.user.DefaultUserDestinationResolver}. + * + * @author Rossen Stoyanchev */ public class DefaultUserDestinationResolverTests { @@ -93,6 +96,18 @@ public class DefaultUserDestinationResolverTests { assertEquals("/queue/foo-user123", actual.iterator().next()); } + @Test + public void handleMessageEncodedUserName() { + + String userName = "http://joe.openid.example.org/"; + this.registry.registerSessionId(userName, "openid123"); + String destination = "/user/" + StringUtils.replace(userName, "/", "%2F") + "/queue/foo"; + Message message = createMessage(SimpMessageType.MESSAGE, this.user, SESSION_ID, destination); + Set actual = this.resolver.resolveDestination(message); + + assertEquals(1, actual.size()); + assertEquals("/queue/foo-useropenid123", actual.iterator().next()); + } @Test public void ignoreMessage() {