View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  //
20  
21  //  ========================================================================
22  //  Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
23  //  ------------------------------------------------------------------------
24  //  All rights reserved. This program and the accompanying materials
25  //  are made available under the terms of the Eclipse Public License v1.0
26  //  and Apache License v2.0 which accompanies this distribution.
27  //
28  //      The Eclipse Public License is available at
29  //      http://www.eclipse.org/legal/epl-v10.html
30  //
31  //      The Apache License v2.0 is available at
32  //      http://www.opensource.org/licenses/apache2.0.php
33  //
34  //  You may elect to redistribute this code under either of these licenses.
35  //  ========================================================================
36  //
37  
38  package com.acme;
39  
40  import java.io.IOException;
41  import java.util.List;
42  import java.util.ListIterator;
43  import java.util.concurrent.CopyOnWriteArrayList;
44  
45  import javax.servlet.ServletException;
46  import javax.servlet.http.HttpServletRequest;
47  import javax.servlet.http.HttpServletResponse;
48  
49  import org.eclipse.jetty.util.FutureCallback;
50  import org.eclipse.jetty.util.log.Log;
51  import org.eclipse.jetty.util.log.Logger;
52  import org.eclipse.jetty.websocket.core.annotations.OnWebSocketClose;
53  import org.eclipse.jetty.websocket.core.annotations.OnWebSocketConnect;
54  import org.eclipse.jetty.websocket.core.annotations.OnWebSocketMessage;
55  import org.eclipse.jetty.websocket.core.annotations.WebSocket;
56  import org.eclipse.jetty.websocket.core.api.UpgradeRequest;
57  import org.eclipse.jetty.websocket.core.api.UpgradeResponse;
58  import org.eclipse.jetty.websocket.core.api.WebSocketConnection;
59  import org.eclipse.jetty.websocket.server.WebSocketCreator;
60  import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
61  import org.eclipse.jetty.websocket.server.WebSocketServlet;
62  
63  @SuppressWarnings("serial")
64  public class WebSocketChatServlet extends WebSocketServlet implements WebSocketCreator
65  {
66      private static final Logger LOG = Log.getLogger(WebSocketChatServlet.class);
67  
68      /** Holds active sockets to other members of the chat */
69      private final List<ChatWebSocket> members = new CopyOnWriteArrayList<ChatWebSocket>();
70  
71      @Override
72      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
73      {
74          getServletContext().getNamedDispatcher("default").forward(request,response);
75      }
76  
77      @Override
78      public Object createWebSocket(UpgradeRequest req, UpgradeResponse resp)
79      {
80          return new ChatWebSocket();
81      }
82  
83      @Override
84      public void registerWebSockets(WebSocketServerFactory factory)
85      {
86          factory.register(ChatWebSocket.class);
87          factory.setCreator(this);
88      }
89  
90      /* ------------------------------------------------------------ */
91      /**
92       * Create a WebSocket that echo's back the message to all other members of the servlet.
93       */
94      @WebSocket
95      public class ChatWebSocket
96      {
97          volatile WebSocketConnection connection;
98  
99          @OnWebSocketConnect
100         public void onOpen(WebSocketConnection conn)
101         {
102             connection = conn;
103             members.add(this);
104         }
105 
106         @OnWebSocketMessage
107         public void onMessage(String data)
108         {
109             if (data.contains("disconnect"))
110             {
111                 connection.close();
112                 return;
113             }
114 
115             ListIterator<ChatWebSocket> iter = members.listIterator();
116             while (iter.hasNext())
117             {
118                 ChatWebSocket member = iter.next();
119 
120                 // Test if member is now disconnected
121                 if (!member.connection.isOpen())
122                 {
123                     iter.remove();
124                     continue;
125                 }
126 
127                 try
128                 {
129                     // Async write the message back.
130                     member.connection.write(null,new FutureCallback<>(),data);
131                 }
132                 catch (IOException e)
133                 {
134                     LOG.warn(e);
135                 }
136             }
137         }
138 
139         @OnWebSocketClose
140         public void onClose(int code, String message)
141         {
142             members.remove(this);
143         }
144     }
145 }