Package asia.stampy.server.listener.login

Source Code of asia.stampy.server.listener.login.AbstractLoginMessageListener

/*
* Copyright (C) 2013 Burton Alexander
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
package asia.stampy.server.listener.login;

import java.lang.invoke.MethodHandles;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import asia.stampy.client.message.connect.ConnectHeader;
import asia.stampy.client.message.connect.ConnectMessage;
import asia.stampy.client.message.stomp.StompMessage;
import asia.stampy.common.StampyLibrary;
import asia.stampy.common.gateway.AbstractStampyMessageGateway;
import asia.stampy.common.gateway.HostPort;
import asia.stampy.common.gateway.MessageListenerHaltException;
import asia.stampy.common.gateway.StampyMessageListener;
import asia.stampy.common.message.StampyMessage;
import asia.stampy.common.message.StompMessageType;
import asia.stampy.common.message.interceptor.InterceptException;
import asia.stampy.server.message.error.ErrorMessage;

/**
* This class enforces login functionality via the implementation of a.
*
* {@link StampyLoginHandler}. Should the login handler throw a
* {@link TerminateSessionException} this class will send an error to the
* client, close the session and throw a {@link MessageListenerHaltException} to
* prevent downstream processing of the message by the remaining
* {@link StampyMessageListener}s.
*/
@StampyLibrary(libraryName = "stampy-client-server")
public abstract class AbstractLoginMessageListener<SVR extends AbstractStampyMessageGateway> implements
    StampyMessageListener {
  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
  private static StompMessageType[] TYPES = StompMessageType.values();

  /** The logged in connections. */
  protected Queue<HostPort> loggedInConnections = new ConcurrentLinkedQueue<HostPort>();

  private StampyLoginHandler loginHandler;
  private SVR gateway;

  /*
   * (non-Javadoc)
   *
   * @see asia.stampy.common.gateway.StampyMessageListener#getMessageTypes()
   */
  @Override
  public StompMessageType[] getMessageTypes() {
    return TYPES;
  }

  /*
   * (non-Javadoc)
   *
   * @see
   * asia.stampy.common.gateway.StampyMessageListener#isForMessage(asia.stampy
   * .common.message.StampyMessage)
   */
  @Override
  public boolean isForMessage(StampyMessage<?> message) {
    return true;
  }

  /*
   * (non-Javadoc)
   *
   * @see asia.stampy.common.gateway.StampyMessageListener#messageReceived(asia.
   * stampy.common.message.StampyMessage, asia.stampy.common.HostPort)
   */
  @Override
  public void messageReceived(StampyMessage<?> message, HostPort hostPort) throws Exception {
    switch (message.getMessageType()) {
    case ABORT:
    case ACK:
    case BEGIN:
    case COMMIT:
    case NACK:
    case SEND:
    case SUBSCRIBE:
    case UNSUBSCRIBE:
      loggedInCheck(message, hostPort);
      break;
    case CONNECT:
      logIn(hostPort, ((ConnectMessage) message).getHeader());
      break;
    case STOMP:
      logIn(hostPort, ((StompMessage) message).getHeader());
      break;
    case DISCONNECT:
      loggedInConnections.remove(hostPort);
      break;
    default:
      String error = "Unexpected message type " + message.getMessageType();
      log.error(error);
      throw new IllegalArgumentException(error);

    }
  }

  private void loggedInCheck(StampyMessage<?> message, HostPort hostPort) throws NotLoggedInException {
    if (loggedInConnections.contains(hostPort)) return;

    log.error("{} attempted to send a {} message without logging in", hostPort, message.getMessageType());
    throw new NotLoggedInException("Not logged in");
  }

  private void logIn(HostPort hostPort, ConnectHeader header) throws AlreadyLoggedInException, NotLoggedInException,
      MessageListenerHaltException {
    if (loggedInConnections.contains(hostPort)) throw new AlreadyLoggedInException(hostPort + " is already logged in");

    if (!isForHeader(header)) throw new NotLoggedInException("login and passcode not specified, cannot log in");

    try {
      getLoginHandler().login(header.getLogin(), header.getPasscode());
      loggedInConnections.add(hostPort);
    } catch (TerminateSessionException e) {
      log.error("Login handler has terminated the session", e);
      sendErrorMessage(e.getMessage(), hostPort);
      gateway.closeConnection(hostPort);
      throw new MessageListenerHaltException();
    }
  }

  private void sendErrorMessage(String message, HostPort hostPort) {
    ErrorMessage error = new ErrorMessage("n/a");
    error.getHeader().setMessageHeader(message);

    try {
      getGateway().sendMessage(error, hostPort);
    } catch (InterceptException e) {
      log.error("Sending of login error message failed", e);
    }
  }

  private boolean isForHeader(ConnectHeader header) {
    return StringUtils.isNotEmpty(header.getLogin()) && StringUtils.isNotEmpty(header.getPasscode());
  }

  /**
   * Gets the login handler.
   *
   * @return the login handler
   */
  public StampyLoginHandler getLoginHandler() {
    return loginHandler;
  }

  /**
   * Inject the implementation of {@link StampyLoginHandler} on system startup.
   *
   * @param loginHandler
   *          the new login handler
   */
  public void setLoginHandler(StampyLoginHandler loginHandler) {
    this.loginHandler = loginHandler;
  }

  /**
   * Gets the gateway.
   *
   * @return the gateway
   */
  public SVR getGateway() {
    return gateway;
  }

  /**
   * Inject the {@link AbstractStampyMessageGateway} on system startup.
   *
   * @param gateway
   *          the new gateway
   */
  public void setGateway(SVR gateway) {
    this.gateway = gateway;
    ensureCleanup();
  }

  /**
   * Configure the gateway to clean up the queue of logged in connections on
   * session termination.
   */
  protected abstract void ensureCleanup();

}
TOP

Related Classes of asia.stampy.server.listener.login.AbstractLoginMessageListener

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.