Add MessageHandler destination prefix checks

This commit is contained in:
Rossen Stoyanchev 2013-07-21 12:06:36 -04:00
parent 2cdac267f7
commit b3c7c18c1b
5 changed files with 94 additions and 42 deletions

View File

@ -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<String> 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<String> destinationPrefixes) {
this.destinationPrefixes = destinationPrefixes;
}
public List<String> 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;

View File

@ -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<String> destinationPrefixes;
private SubscriptionRegistry subscriptionRegistry = new DefaultSubscriptionRegistry();
@ -51,6 +55,14 @@ public class SimpleBrokerMessageHandler implements MessageHandler {
}
public void setDestinationPrefixes(List<String> destinationPrefixes) {
this.destinationPrefixes = destinationPrefixes;
}
public List<String> 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);

View File

@ -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<String> messagingTemplate;
private String prefix = "/user/";
private String destinationPrefix = "/user/";
private UserQueueSuffixResolver userQueueSuffixResolver = new SimpleUserQueueSuffixResolver();
@ -72,16 +71,16 @@ public class UserDestinationMessageHandler implements MessageHandler {
* <p>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) {

View File

@ -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;

View File

@ -83,7 +83,7 @@ public class MappingJackson2MessageConverter implements MessageConverter<Object>
}
}
catch (IOException ex) {
throw new MessageConversionException("Could not read JSON: " + ex.getMessage(), ex);
throw new MessageConversionException(message, "Could not read JSON: " + ex.getMessage(), ex);
}
}