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  package org.eclipse.jetty.websocket.servlet;
20  
21  import java.io.IOException;
22  
23  import javax.servlet.ServletException;
24  import javax.servlet.http.HttpServlet;
25  import javax.servlet.http.HttpServletRequest;
26  import javax.servlet.http.HttpServletResponse;
27  
28  import org.eclipse.jetty.websocket.api.WebSocketBehavior;
29  import org.eclipse.jetty.websocket.api.WebSocketPolicy;
30  import org.eclipse.jetty.websocket.api.annotations.WebSocket;
31  
32  /**
33   * Abstract Servlet used to bridge the Servlet API to the WebSocket API.
34   * <p>
35   * To use this servlet, you will be required to register your websockets with the {@link WebSocketServletFactory} so that it can create your websockets under the
36   * appropriate conditions.
37   * <p>
38   * The most basic implementation would be as follows.
39   * 
40   * <pre>
41   * package my.example;
42   * 
43   * import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
44   * import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
45   * 
46   * public class MyEchoServlet extends WebSocketServlet
47   * {
48   *     &#064;Override
49   *     public void configure(WebSocketServletFactory factory)
50   *     {
51   *         // set a 10 second idle timeout
52   *         factory.getPolicy().setIdleTimeout(10000);
53   *         // register my socket
54   *         factory.register(MyEchoSocket.class);
55   *     }
56   * }
57   * </pre>
58   * 
59   * Note: that only request that conforms to a "WebSocket: Upgrade" handshake request will trigger the {@link WebSocketServletFactory} handling of creating
60   * WebSockets.<br>
61   * All other requests are treated as normal servlet requests.
62   * 
63   * <p>
64   * <b>Configuration / Init-Parameters:</b><br>
65   * Note: If you use the {@link WebSocket &#064;WebSocket} annotation, these configuration settings can be specified on a per WebSocket basis, vs a per Servlet
66   * basis.
67   * 
68   * <dl>
69   * <dt>maxIdleTime</dt>
70   * <dd>set the time in ms that a websocket may be idle before closing<br>
71   * 
72   * <dt>maxTextMessageSize</dt>
73   * <dd>set the size in UTF-8 bytes that a websocket may be accept as a Text Message before closing<br>
74   * 
75   * <dt>maxBinaryMessageSize</dt>
76   * <dd>set the size in bytes that a websocket may be accept as a Binary Message before closing<br>
77   * 
78   * <dt>inputBufferSize</dt>
79   * <dd>set the size in bytes of the buffer used to read raw bytes from the network layer<br>
80   * </dl>
81   */
82  @SuppressWarnings("serial")
83  public abstract class WebSocketServlet extends HttpServlet
84  {
85      private WebSocketServletFactory factory;
86  
87      public abstract void configure(WebSocketServletFactory factory);
88  
89      @Override
90      public void destroy()
91      {
92          factory.cleanup();
93      }
94  
95      /**
96       * @see javax.servlet.GenericServlet#init()
97       */
98      @Override
99      public void init() throws ServletException
100     {
101         try
102         {
103             WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
104 
105             String max = getInitParameter("maxIdleTime");
106             if (max != null)
107             {
108                 policy.setIdleTimeout(Long.parseLong(max));
109             }
110 
111             max = getInitParameter("maxTextMessageSize");
112             if (max != null)
113             {
114                 policy.setMaxTextMessageSize(Integer.parseInt(max));
115             }
116 
117             max = getInitParameter("maxBinaryMessageSize");
118             if (max != null)
119             {
120                 policy.setMaxBinaryMessageSize(Integer.parseInt(max));
121             }
122 
123             max = getInitParameter("inputBufferSize");
124             if (max != null)
125             {
126                 policy.setInputBufferSize(Integer.parseInt(max));
127             }
128 
129             factory = WebSocketServletFactory.Loader.create(policy);
130 
131             configure(factory);
132 
133             factory.init();
134         }
135         catch (Exception x)
136         {
137             throw new ServletException(x);
138         }
139     }
140 
141     /**
142      * @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
143      */
144     @Override
145     protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
146     {
147         if (factory.isUpgradeRequest(request,response))
148         {
149             // We have an upgrade request
150             if (factory.acceptWebSocket(request,response))
151             {
152                 // We have a socket instance created
153                 return;
154             }
155             // If we reach this point, it means we had an incoming request to upgrade
156             // but it was either not a proper websocket upgrade, or it was possibly rejected
157             // due to incoming request constraints (controlled by WebSocketCreator)
158             if (response.isCommitted())
159             {
160                 // not much we can do at this point.
161                 return;
162             }
163         }
164 
165         // All other processing
166         super.service(request,response);
167     }
168 }