001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.mina.example.chat; 021 022import java.util.Collections; 023import java.util.HashSet; 024import java.util.Set; 025 026import org.apache.mina.core.service.IoHandler; 027import org.apache.mina.core.service.IoHandlerAdapter; 028import org.apache.mina.core.session.IoSession; 029import org.apache.mina.filter.logging.MdcInjectionFilter; 030import org.slf4j.Logger; 031import org.slf4j.LoggerFactory; 032 033/** 034 * {@link IoHandler} implementation of a simple chat server protocol. 035 * 036 * @author <a href="http://mina.apache.org">Apache MINA Project</a> 037 */ 038public class ChatProtocolHandler extends IoHandlerAdapter { 039 private final static Logger LOGGER = LoggerFactory.getLogger(ChatProtocolHandler.class); 040 041 private final Set<IoSession> sessions = Collections 042 .synchronizedSet(new HashSet<IoSession>()); 043 044 private final Set<String> users = Collections 045 .synchronizedSet(new HashSet<String>()); 046 047 @Override 048 public void exceptionCaught(IoSession session, Throwable cause) { 049 LOGGER.warn("Unexpected exception.", cause); 050 // Close connection when unexpected exception is caught. 051 session.closeNow(); 052 } 053 054 @Override 055 public void messageReceived(IoSession session, Object message) { 056 Logger log = LoggerFactory.getLogger(ChatProtocolHandler.class); 057 log.info("received: " + message); 058 String theMessage = (String) message; 059 String[] result = theMessage.split(" ", 2); 060 String theCommand = result[0]; 061 062 try { 063 064 ChatCommand command = ChatCommand.valueOf(theCommand); 065 String user = (String) session.getAttribute("user"); 066 067 switch (command.toInt()) { 068 069 case ChatCommand.QUIT: 070 session.write("QUIT OK"); 071 session.closeNow(); 072 break; 073 case ChatCommand.LOGIN: 074 075 if (user != null) { 076 session.write("LOGIN ERROR user " + user 077 + " already logged in."); 078 return; 079 } 080 081 if (result.length == 2) { 082 user = result[1]; 083 } else { 084 session.write("LOGIN ERROR invalid login command."); 085 return; 086 } 087 088 // check if the username is already used 089 if (users.contains(user)) { 090 session.write("LOGIN ERROR the name " + user 091 + " is already used."); 092 return; 093 } 094 095 sessions.add(session); 096 session.setAttribute("user", user); 097 MdcInjectionFilter.setProperty(session, "user", user); 098 099 // Allow all users 100 users.add(user); 101 session.write("LOGIN OK"); 102 broadcast("The user " + user + " has joined the chat session."); 103 break; 104 105 case ChatCommand.BROADCAST: 106 107 if (result.length == 2) { 108 broadcast(user + ": " + result[1]); 109 } 110 break; 111 default: 112 LOGGER.info("Unhandled command: " + command); 113 break; 114 } 115 116 } catch (IllegalArgumentException e) { 117 LOGGER.debug("Illegal argument", e); 118 } 119 } 120 121 public void broadcast(String message) { 122 synchronized (sessions) { 123 for (IoSession session : sessions) { 124 if (session.isConnected()) { 125 session.write("BROADCAST OK " + message); 126 } 127 } 128 } 129 } 130 131 @Override 132 public void sessionClosed(IoSession session) throws Exception { 133 String user = (String) session.getAttribute("user"); 134 users.remove(user); 135 sessions.remove(session); 136 broadcast("The user " + user + " has left the chat session."); 137 } 138 139 public boolean isChatUser(String name) { 140 return users.contains(name); 141 } 142 143 public int getNumberOfUsers() { 144 return users.size(); 145 } 146 147 public void kick(String name) { 148 synchronized (sessions) { 149 for (IoSession session : sessions) { 150 if (name.equals(session.getAttribute("user"))) { 151 session.closeNow(); 152 break; 153 } 154 } 155 } 156 } 157}