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.closeNow();
52      }
53  
54      @Override
55      public void messageSent(IoSession session, Object message) {
56          System.out.println( message );
57      }
58  
59      @Override
60      public void messageReceived(IoSession session, Object message) {
61          Logger log = LoggerFactory.getLogger(ChatProtocolHandler.class);
62          log.info("received: " + message);
63          String theMessage = (String) message;
64          String[] result = theMessage.split(" ", 2);
65          String theCommand = result[0];
66  
67          try {
68  
69              ChatCommand command = ChatCommand.valueOf(theCommand);
70              String user = (String) session.getAttribute("user");
71  
72              switch (command.toInt()) {
73  
74              case ChatCommand.QUIT:
75                  session.write("QUIT OK");
76                  session.closeNow();
77                  break;
78              case ChatCommand.LOGIN:
79  
80                  if (user != null) {
81                      session.write("LOGIN ERROR user " + user
82                              + " already logged in.");
83                      return;
84                  }
85  
86                  if (result.length == 2) {
87                      user = result[1];
88                  } else {
89                      session.write("LOGIN ERROR invalid login command.");
90                      return;
91                  }
92  
93                  // check if the username is already used
94                  if (users.contains(user)) {
95                      session.write("LOGIN ERROR the name " + user
96                              + " is already used.");
97                      return;
98                  }
99  
100                 sessions.add(session);
101                 session.setAttribute("user", user);
102                 MdcInjectionFilter.setProperty(session, "user", user);
103 
104                 // Allow all users
105                 users.add(user);
106                 session.write("LOGIN OK");
107                 broadcast("The user " + user + " has joined the chat session.");
108                 break;
109 
110             case ChatCommand.BROADCAST:
111 
112                 if (result.length == 2) {
113                     broadcast(user + ": " + result[1]);
114                 }
115                 break;
116             default:
117                 LOGGER.info("Unhandled command: " + command);
118                 break;
119             }
120 
121         } catch (IllegalArgumentException e) {
122             LOGGER.debug("Illegal argument", e);
123         }
124     }
125 
126     public void broadcast(String message) {
127         synchronized (sessions) {
128             for (IoSession session : sessions) {
129                 if (session.isConnected()) {
130                     session.write("BROADCAST OK " + message);
131                 }
132             }
133         }
134     }
135 
136     @Override
137     public void sessionClosed(IoSession session) throws Exception {
138         String user = (String) session.getAttribute("user");
139         users.remove(user);
140         sessions.remove(session);
141         broadcast("The user " + user + " has left the chat session.");
142     }
143 
144     public boolean isChatUser(String name) {
145         return users.contains(name);
146     }
147 
148     public int getNumberOfUsers() {
149         return users.size();
150     }
151 
152     public void kick(String name) {
153         synchronized (sessions) {
154             for (IoSession session : sessions) {
155                 if (name.equals(session.getAttribute("user"))) {
156                     session.closeNow();
157                     break;
158                 }
159             }
160         }
161     }
162 }