View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.mina.example.chat;
21  
22  import java.util.Collections;
23  import java.util.HashSet;
24  import java.util.Set;
25  
26  import org.apache.mina.core.service.IoHandler;
27  import org.apache.mina.core.service.IoHandlerAdapter;
28  import org.apache.mina.core.session.IoSession;
29  import org.apache.mina.filter.logging.MdcInjectionFilter;
30  import org.slf4j.Logger;
31  import org.slf4j.LoggerFactory;
32  
33  /**
34   * {@link IoHandler} implementation of a simple chat server protocol.
35   *
36   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
37   */
38  public class ChatProtocolHandler extends IoHandlerAdapter {
39      private final static Logger LOGGER = LoggerFactory.getLogger(ChatProtocolHandler.class);
40  
41      private final Set<IoSession> sessions = Collections
42              .synchronizedSet(new HashSet<IoSession>());
43  
44      private final Set<String> users = Collections
45              .synchronizedSet(new HashSet<String>());
46  
47      @Override
48      public void exceptionCaught(IoSession session, Throwable cause) {
49          LOGGER.warn("Unexpected exception.", cause);
50          // Close connection when unexpected exception is caught.
51          session.close(true);
52      }
53  
54      @Override
55      public void messageReceived(IoSession session, Object message) {
56          Logger log = LoggerFactory.getLogger(ChatProtocolHandler.class);
57          log.info("received: " + message);
58          String theMessage = (String) message;
59          String[] result = theMessage.split(" ", 2);
60          String theCommand = result[0];
61  
62          try {
63  
64              ChatCommand command = ChatCommand.valueOf(theCommand);
65              String user = (String) session.getAttribute("user");
66  
67              switch (command.toInt()) {
68  
69              case ChatCommand.QUIT:
70                  session.write("QUIT OK");
71                  session.close(true);
72                  break;
73              case ChatCommand.LOGIN:
74  
75                  if (user != null) {
76                      session.write("LOGIN ERROR user " + user
77                              + " already logged in.");
78                      return;
79                  }
80  
81                  if (result.length == 2) {
82                      user = result[1];
83                  } else {
84                      session.write("LOGIN ERROR invalid login command.");
85                      return;
86                  }
87  
88                  // check if the username is already used
89                  if (users.contains(user)) {
90                      session.write("LOGIN ERROR the name " + user
91                              + " is already used.");
92                      return;
93                  }
94  
95                  sessions.add(session);
96                  session.setAttribute("user", user);
97                  MdcInjectionFilter.setProperty(session, "user", user);
98  
99                  // 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.close(true);
152                     break;
153                 }
154             }
155         }
156     }
157 }