View Javadoc

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