From b3c7c18c1b800a800c1748a7b85d65eae40ff94f Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Sun, 21 Jul 2013 12:06:36 -0400 Subject: [PATCH] Add MessageHandler destination prefix checks --- .../AnnotationMethodMessageHandler.java | 42 ++++++++++++++-- .../handler/SimpleBrokerMessageHandler.java | 28 +++++++++++ .../UserDestinationMessageHandler.java | 50 ++++++++----------- .../stomp/StompBrokerRelayMessageHandler.java | 14 +++--- .../MappingJackson2MessageConverter.java | 2 +- 5 files changed, 94 insertions(+), 42 deletions(-) diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/handler/AnnotationMethodMessageHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/handler/AnnotationMethodMessageHandler.java index a51370a8558..f6d31a17a8c 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/handler/AnnotationMethodMessageHandler.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/handler/AnnotationMethodMessageHandler.java @@ -42,6 +42,7 @@ import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.ReplyTo; import org.springframework.messaging.handler.annotation.support.ExceptionHandlerMethodResolver; import org.springframework.messaging.handler.annotation.support.MessageBodyMethodArgumentResolver; +import org.springframework.messaging.handler.annotation.support.MessageMethodArgumentResolver; import org.springframework.messaging.handler.method.HandlerMethod; import org.springframework.messaging.handler.method.HandlerMethodArgumentResolverComposite; import org.springframework.messaging.handler.method.HandlerMethodReturnValueHandlerComposite; @@ -75,6 +76,8 @@ public class AnnotationMethodMessageHandler implements MessageHandler, Applicati private final SimpMessageSendingOperations webSocketSessionMessagingTemplate; + private List destinationPrefixes; + private MessageConverter messageConverter; private ApplicationContext applicationContext; @@ -110,9 +113,15 @@ public class AnnotationMethodMessageHandler implements MessageHandler, Applicati this.webSocketSessionMessagingTemplate = new SimpMessagingTemplate(webSocketSessionChannel); } - /** - * TODO: multiple converters with 'content-type' header - */ + + public void setDestinationPrefixes(List destinationPrefixes) { + this.destinationPrefixes = destinationPrefixes; + } + + public List getDestinationPrefixes() { + return this.destinationPrefixes; + } + public void setMessageConverter(MessageConverter converter) { this.messageConverter = converter; if (converter != null) { @@ -120,6 +129,10 @@ public class AnnotationMethodMessageHandler implements MessageHandler, Applicati } } + public MessageConverter getMessageConverter() { + return this.messageConverter; + } + @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; @@ -131,6 +144,7 @@ public class AnnotationMethodMessageHandler implements MessageHandler, Applicati initHandlerMethods(); this.argumentResolvers.addResolver(new PrincipalMethodArgumentResolver()); + this.argumentResolvers.addResolver(new MessageMethodArgumentResolver()); this.argumentResolvers.addResolver(new MessageBodyMethodArgumentResolver(this.messageConverter)); this.returnValueHandlers.addHandler(new ReplyToMethodReturnValueHandler(this.dispatchMessagingTemplate)); @@ -147,8 +161,7 @@ public class AnnotationMethodMessageHandler implements MessageHandler, Applicati } protected boolean isHandler(Class beanType) { - return ((AnnotationUtils.findAnnotation(beanType, Controller.class) != null) || - (AnnotationUtils.findAnnotation(beanType, MessageMapping.class) != null)); + return (AnnotationUtils.findAnnotation(beanType, Controller.class) != null); } protected void detectHandlerMethods(Object handler) { @@ -220,11 +233,19 @@ public class AnnotationMethodMessageHandler implements MessageHandler, Applicati SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.wrap(message); String destination = headers.getDestination(); + if (!checkDestinationPrefix(destination)) { + return; + } + HandlerMethod match = getHandlerMethod(destination, handlerMethods); if (match == null) { return; } + if (logger.isTraceEnabled()) { + logger.trace("Processing message: " + message); + } + HandlerMethod handlerMethod = match.createWithResolvedBean(); InvocableHandlerMethod invocableHandlerMethod = new InvocableHandlerMethod(handlerMethod); @@ -248,6 +269,17 @@ public class AnnotationMethodMessageHandler implements MessageHandler, Applicati } } + private boolean checkDestinationPrefix(String destination) { + if ((destination != null) && (this.destinationPrefixes != null)) { + for (String prefix : this.destinationPrefixes) { + if (destination.startsWith(prefix)) { + return true; + } + } + } + return false; + } + private void invokeExceptionHandler(Message message, HandlerMethod handlerMethod, Exception ex) { InvocableHandlerMethod exceptionHandlerMethod; diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/handler/SimpleBrokerMessageHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/handler/SimpleBrokerMessageHandler.java index 3d14e3af641..48a20cefd2c 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/handler/SimpleBrokerMessageHandler.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/handler/SimpleBrokerMessageHandler.java @@ -16,6 +16,8 @@ package org.springframework.messaging.simp.handler; +import java.util.List; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.messaging.Message; @@ -39,6 +41,8 @@ public class SimpleBrokerMessageHandler implements MessageHandler { private final MessageChannel messageChannel; + private List destinationPrefixes; + private SubscriptionRegistry subscriptionRegistry = new DefaultSubscriptionRegistry(); @@ -51,6 +55,14 @@ public class SimpleBrokerMessageHandler implements MessageHandler { } + public void setDestinationPrefixes(List destinationPrefixes) { + this.destinationPrefixes = destinationPrefixes; + } + + public List getDestinationPrefixes() { + return this.destinationPrefixes; + } + public void setSubscriptionRegistry(SubscriptionRegistry subscriptionRegistry) { Assert.notNull(subscriptionRegistry, "subscriptionRegistry is required"); this.subscriptionRegistry = subscriptionRegistry; @@ -65,6 +77,11 @@ public class SimpleBrokerMessageHandler implements MessageHandler { SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.wrap(message); SimpMessageType messageType = headers.getMessageType(); + String destination = headers.getDestination(); + + if (!checkDestinationPrefix(destination)) { + return; + } if (SimpMessageType.SUBSCRIBE.equals(messageType)) { preProcessMessage(message); @@ -85,6 +102,17 @@ public class SimpleBrokerMessageHandler implements MessageHandler { } } + private boolean checkDestinationPrefix(String destination) { + if ((destination != null) && (this.destinationPrefixes != null)) { + for (String prefix : this.destinationPrefixes) { + if (destination.startsWith(prefix)) { + return true; + } + } + } + return false; + } + private void preProcessMessage(Message message) { if (logger.isTraceEnabled()) { logger.trace("Processing " + message); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/handler/UserDestinationMessageHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/handler/UserDestinationMessageHandler.java index 91843e92874..d27db9946b5 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/handler/UserDestinationMessageHandler.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/handler/UserDestinationMessageHandler.java @@ -26,7 +26,6 @@ import org.springframework.messaging.simp.SimpMessageHeaderAccessor; import org.springframework.messaging.simp.SimpMessageType; import org.springframework.messaging.support.MessageBuilder; import org.springframework.util.Assert; -import org.springframework.util.StringUtils; /** @@ -48,7 +47,7 @@ public class UserDestinationMessageHandler implements MessageHandler { private final MessageSendingOperations messagingTemplate; - private String prefix = "/user/"; + private String destinationPrefix = "/user/"; private UserQueueSuffixResolver userQueueSuffixResolver = new SimpleUserQueueSuffixResolver(); @@ -72,16 +71,16 @@ public class UserDestinationMessageHandler implements MessageHandler { *

The default prefix is "/user". * @param prefix the prefix to set */ - public void setPrefix(String prefix) { + public void setDestinationPrefix(String prefix) { Assert.hasText(prefix, "prefix is required"); - this.prefix = prefix.endsWith("/") ? prefix : prefix + "/"; + this.destinationPrefix = prefix.endsWith("/") ? prefix : prefix + "/"; } /** * @return the prefix */ - public String getPrefix() { - return this.prefix; + public String getDestinationPrefix() { + return this.destinationPrefix; } /** @@ -101,12 +100,17 @@ public class UserDestinationMessageHandler implements MessageHandler { @Override public void handleMessage(Message message) throws MessagingException { - if (!shouldHandle(message)) { + SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.wrap(message); + SimpMessageType messageType = headers.getMessageType(); + String destination = headers.getDestination(); + + if (!SimpMessageType.MESSAGE.equals(messageType)) { return; } - SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.wrap(message); - String destination = headers.getDestination(); + if (!checkDestination(destination)) { + return; + } if (logger.isTraceEnabled()) { logger.trace("Processing message to destination " + destination); @@ -117,7 +121,7 @@ public class UserDestinationMessageHandler implements MessageHandler { if (user == null) { if (logger.isErrorEnabled()) { - logger.error("Ignoring message, expected destination \"" + this.prefix + logger.error("Ignoring message, expected destination pattern \"" + this.destinationPrefix + "{userId}/**\": " + destination); } return; @@ -136,27 +140,13 @@ public class UserDestinationMessageHandler implements MessageHandler { } } - protected boolean shouldHandle(Message message) { - - SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.wrap(message); - SimpMessageType messageType = headers.getMessageType(); - String destination = headers.getDestination(); - - if (!SimpMessageType.MESSAGE.equals(messageType)) { - return false; - } - - if (!StringUtils.hasText(destination)) { - if (logger.isErrorEnabled()) { - logger.error("Ignoring message, no destination: " + headers); + private boolean checkDestination(String destination) { + if (destination != null) { + if (destination.startsWith(this.destinationPrefix)) { + return true; } - return false; } - else if (!destination.startsWith(this.prefix)) { - return false; - } - - return true; + return false; } @@ -169,7 +159,7 @@ public class UserDestinationMessageHandler implements MessageHandler { public UserDestinationParser(String destination) { - int userStartIndex = prefix.length(); + int userStartIndex = destinationPrefix.length(); int userEndIndex = destination.indexOf('/', userStartIndex); if (userEndIndex > 0) { diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompBrokerRelayMessageHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompBrokerRelayMessageHandler.java index ce4156a173c..0f45bde028a 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompBrokerRelayMessageHandler.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompBrokerRelayMessageHandler.java @@ -285,13 +285,9 @@ public class StompBrokerRelayMessageHandler implements MessageHandler, SmartLife logger.error("Ignoring message, no sessionId: " + message); return; } - if (command.requiresDestination() && (destination == null)) { - logger.error("Ignoring " + command + " message, no destination: " + message); - return; - } try { - if ((destination == null) || supportsDestination(destination)) { + if (checkDestinationPrefix(command, destination)) { if (logger.isTraceEnabled()) { logger.trace("Processing message: " + message); @@ -329,7 +325,13 @@ public class StompBrokerRelayMessageHandler implements MessageHandler, SmartLife } } - protected boolean supportsDestination(String destination) { + protected boolean checkDestinationPrefix(StompCommand command, String destination) { + if (!command.requiresDestination()) { + return true; + } + else if (destination == null) { + return false; + } for (String prefix : this.destinationPrefixes) { if (destination.startsWith(prefix)) { return true; diff --git a/spring-messaging/src/main/java/org/springframework/messaging/support/converter/MappingJackson2MessageConverter.java b/spring-messaging/src/main/java/org/springframework/messaging/support/converter/MappingJackson2MessageConverter.java index e41c73dad60..d0c380605f7 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/support/converter/MappingJackson2MessageConverter.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/support/converter/MappingJackson2MessageConverter.java @@ -83,7 +83,7 @@ public class MappingJackson2MessageConverter implements MessageConverter } } catch (IOException ex) { - throw new MessageConversionException("Could not read JSON: " + ex.getMessage(), ex); + throw new MessageConversionException(message, "Could not read JSON: " + ex.getMessage(), ex); } }