Package org.springframework.messaging.simp.user

Source Code of org.springframework.messaging.simp.user.UserDestinationMessageHandler

/*
* 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.user;

import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.context.SmartLifecycle;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessagingException;
import org.springframework.messaging.SubscribableChannel;
import org.springframework.messaging.core.MessageSendingOperations;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.messaging.simp.SimpMessageType;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.messaging.support.MessageHeaderInitializer;
import org.springframework.util.Assert;

/**
* Provides support for messages sent to "user" destinations, translating the
* destination to one or more user-specific destination(s) and then sending message(s)
* with the updated target destination using the provided messaging template.
* <p>
* See {@link UserDestinationResolver} for more details and examples.
*
* @author Rossen Stoyanchev
* @since 4.0
*/
public class UserDestinationMessageHandler implements MessageHandler, SmartLifecycle {

  private static final Log logger = LogFactory.getLog(UserDestinationMessageHandler.class);


  private final SubscribableChannel clientInboundChannel;

  private final SubscribableChannel brokerChannel;

  private final MessageSendingOperations<String> brokerMessagingTemplate;

  private final UserDestinationResolver userDestinationResolver;

  private MessageHeaderInitializer headerInitializer;

  private final Object lifecycleMonitor = new Object();

  private volatile boolean running = false;


  /**
   * Create an instance of the handler with the given messaging template and a
   * user destination resolver.
   * @param clientInChannel the channel for receiving messages from clients (e.g. WebSocket clients)
   * @param brokerChannel the channel for sending messages with translated user destinations
   * @param userDestinationResolver the resolver to use to find queue suffixes for a user
   */
  public UserDestinationMessageHandler(SubscribableChannel clientInChannel,
      SubscribableChannel brokerChannel, UserDestinationResolver userDestinationResolver) {

    Assert.notNull(clientInChannel, "'clientInChannel' must not be null");
    Assert.notNull(brokerChannel, "'brokerChannel' must not be null");
    Assert.notNull(userDestinationResolver, "DestinationResolver must not be null");

    this.clientInboundChannel = clientInChannel;
    this.brokerChannel = brokerChannel;
    this.brokerMessagingTemplate = new SimpMessagingTemplate(brokerChannel);
    this.userDestinationResolver = userDestinationResolver;
  }


  /**
   * Return the configured messaging template for sending messages with
   * translated destinations.
   */
  public MessageSendingOperations<String> getBrokerMessagingTemplate() {
    return this.brokerMessagingTemplate;
  }

  /**
   * Return the configured {@link UserDestinationResolver}.
   */
  public UserDestinationResolver getUserDestinationResolver() {
    return this.userDestinationResolver;
  }

  /**
   * Configure a {@link MessageHeaderInitializer} to pass on to
   * {@link org.springframework.messaging.handler.invocation.HandlerMethodReturnValueHandler}s
   * that send messages from controller return values.
   *
   * <p>By default this property is not set.
   */
  public void setHeaderInitializer(MessageHeaderInitializer headerInitializer) {
    this.headerInitializer = headerInitializer;
  }

  /**
   * @return the configured header initializer.
   */
  public MessageHeaderInitializer getHeaderInitializer() {
    return this.headerInitializer;
  }


  @Override
  public int getPhase() {
    return Integer.MAX_VALUE;
  }

  @Override
  public boolean isAutoStartup() {
    return true;
  }

  @Override
  public final boolean isRunning() {
    synchronized (this.lifecycleMonitor) {
      return this.running;
    }
  }

  @Override
  public final void start() {
    synchronized (this.lifecycleMonitor) {
      this.clientInboundChannel.subscribe(this);
      this.brokerChannel.subscribe(this);
      this.running = true;
    }
  }

  @Override
  public final void stop() {
    synchronized (this.lifecycleMonitor) {
      this.running = false;
      this.clientInboundChannel.unsubscribe(this);
      this.brokerChannel.unsubscribe(this);
    }
  }

  @Override
  public final void stop(Runnable callback) {
    synchronized (this.lifecycleMonitor) {
      stop();
      callback.run();
    }
  }


  @Override
  public void handleMessage(Message<?> message) throws MessagingException {
    UserDestinationResult result = this.userDestinationResolver.resolveDestination(message);
    if (result == null) {
      return;
    }
    Set<String> destinations = result.getTargetDestinations();
    if (destinations.isEmpty()) {
      if (logger.isTraceEnabled()) {
        logger.trace("No user destinations found for " + result.getSourceDestination());
      }
      return;
    }
    if (SimpMessageType.MESSAGE.equals(SimpMessageHeaderAccessor.getMessageType(message.getHeaders()))) {
      SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.wrap(message);
      initHeaders(headerAccessor);
      String header = SimpMessageHeaderAccessor.ORIGINAL_DESTINATION;
      headerAccessor.setNativeHeader(header, result.getSubscribeDestination());
      message = MessageBuilder.createMessage(message.getPayload(), headerAccessor.getMessageHeaders());
    }
    if (logger.isDebugEnabled()) {
      logger.debug("Translated " + result.getSourceDestination() + " -> " + destinations);
    }
    for (String destination : destinations) {
      this.brokerMessagingTemplate.send(destination, message);
    }
  }

  private void initHeaders(SimpMessageHeaderAccessor headerAccessor) {
    if (getHeaderInitializer() != null) {
      getHeaderInitializer().initHeaders(headerAccessor);
    }
  }

  @Override
  public String toString() {
    return "UserDestinationMessageHandler[" + this.userDestinationResolver + "]";
  }

}
TOP

Related Classes of org.springframework.messaging.simp.user.UserDestinationMessageHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.