View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 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.websocket.api.RemoteEndpoint;
50  import org.eclipse.jetty.websocket.api.Session;
51  import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
52  import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
53  import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
54  import org.eclipse.jetty.websocket.api.annotations.WebSocket;
55  import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
56  import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
57  import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
58  import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
59  import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
60  
61  @SuppressWarnings("serial")
62  public class WebSocketChatServlet extends WebSocketServlet implements WebSocketCreator
63  {
64      /** Holds active sockets to other members of the chat */
65      private final List<ChatWebSocket> members = new CopyOnWriteArrayList<ChatWebSocket>();
66  
67      @Override
68      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
69      {
70          getServletContext().getNamedDispatcher("default").forward(request,response);
71      }
72  
73      @Override
74      public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp)
75      {
76          if (req.hasSubProtocol("chat"))
77          {
78              resp.setAcceptedSubProtocol("chat");
79              return new ChatWebSocket();
80          }
81          return null;
82      }
83  
84      @Override
85      public void configure(WebSocketServletFactory factory)
86      {
87          factory.register(ChatWebSocket.class);
88          factory.setCreator(this);
89      }
90  
91      /* ------------------------------------------------------------ */
92      /**
93       * Create a WebSocket that echo's back the message to all other members of the servlet.
94       */
95      @WebSocket
96      public class ChatWebSocket
97      {
98          volatile Session session;
99          volatile RemoteEndpoint remote;
100 
101         @OnWebSocketConnect
102         public void onOpen(Session sess)
103         {
104             this.session = sess;
105             this.remote = sess.getRemote();
106             members.add(this);
107         }
108 
109         @OnWebSocketMessage
110         public void onMessage(String data)
111         {
112             if (data.contains("disconnect"))
113             {
114                 session.close();
115                 return;
116             }
117 
118             ListIterator<ChatWebSocket> iter = members.listIterator();
119             while (iter.hasNext())
120             {
121                 ChatWebSocket member = iter.next();
122 
123                 // Test if member is now disconnected
124                 if (!member.session.isOpen())
125                 {
126                     iter.remove();
127                     continue;
128                 }
129 
130                 // Async write the message back.
131                 member.remote.sendString(data,null);
132             }
133         }
134 
135         @OnWebSocketClose
136         public void onClose(int code, String message)
137         {
138             members.remove(this);
139         }
140     }
141 }