View Javadoc

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