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.jsr356.server;
20  
21  import java.io.IOException;
22  import java.util.ArrayList;
23  import java.util.List;
24  
25  import javax.websocket.Extension;
26  import javax.websocket.Extension.Parameter;
27  import javax.websocket.server.ServerEndpointConfig;
28  
29  import org.eclipse.jetty.util.log.Log;
30  import org.eclipse.jetty.util.log.Logger;
31  import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
32  import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
33  import org.eclipse.jetty.websocket.jsr356.JsrExtension;
34  import org.eclipse.jetty.websocket.jsr356.endpoints.EndpointInstance;
35  import org.eclipse.jetty.websocket.jsr356.server.pathmap.WebSocketPathSpec;
36  import org.eclipse.jetty.websocket.server.pathmap.PathSpec;
37  import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
38  import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
39  import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
40  
41  public class JsrCreator implements WebSocketCreator
42  {
43      private static final Logger LOG = Log.getLogger(JsrCreator.class);
44      private final ServerEndpointMetadata metadata;
45      private final ExtensionFactory extensionFactory;
46  
47      public JsrCreator(ServerEndpointMetadata metadata, ExtensionFactory extensionFactory)
48      {
49          this.metadata = metadata;
50          this.extensionFactory = extensionFactory;
51      }
52  
53      @Override
54      public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp)
55      {
56          JsrHandshakeRequest hsreq = new JsrHandshakeRequest(req);
57          JsrHandshakeResponse hsresp = new JsrHandshakeResponse(resp);
58  
59          ServerEndpointConfig config = metadata.getConfig();
60  
61          ServerEndpointConfig.Configurator configurator = config.getConfigurator();
62  
63          // modify handshake
64          configurator.modifyHandshake(config,hsreq,hsresp);
65  
66          // check origin
67          if (!configurator.checkOrigin(req.getOrigin()))
68          {
69              try
70              {
71                  resp.sendForbidden("Origin mismatch");
72              }
73              catch (IOException e)
74              {
75                  LOG.debug("Unable to send error response",e);
76              }
77              return null;
78          }
79  
80          // deal with sub protocols
81          List<String> supported = config.getSubprotocols();
82          List<String> requested = req.getSubProtocols();
83          String subprotocol = configurator.getNegotiatedSubprotocol(supported,requested);
84          if (subprotocol != null)
85          {
86              resp.setAcceptedSubProtocol(subprotocol);
87          }
88  
89          // deal with extensions
90          List<Extension> installedExts = new ArrayList<>();
91          for (String extName : extensionFactory.getAvailableExtensions().keySet())
92          {
93              installedExts.add(new JsrExtension(extName));
94          }
95          List<Extension> requestedExts = new ArrayList<>();
96          for (ExtensionConfig reqCfg : req.getExtensions())
97          {
98              requestedExts.add(new JsrExtension(reqCfg));
99          }
100         List<Extension> usedExts = configurator.getNegotiatedExtensions(installedExts,requestedExts);
101         List<ExtensionConfig> configs = new ArrayList<>();
102         if (usedExts != null)
103         {
104             for (Extension used : usedExts)
105             {
106                 ExtensionConfig ecfg = new ExtensionConfig(used.getName());
107                 for (Parameter param : used.getParameters())
108                 {
109                     ecfg.setParameter(param.getName(),param.getValue());
110                 }
111                 configs.add(ecfg);
112             }
113         }
114         resp.setExtensions(configs);
115 
116         // create endpoint class
117         try
118         {
119             Class<?> endpointClass = config.getEndpointClass();
120             Object endpoint = config.getConfigurator().getEndpointInstance(endpointClass);
121             PathSpec pathSpec = hsreq.getRequestPathSpec();
122             if (pathSpec instanceof WebSocketPathSpec)
123             {
124                 // We have a PathParam path spec
125                 WebSocketPathSpec wspathSpec = (WebSocketPathSpec)pathSpec;
126                 String requestPath = req.getRequestPath();
127                 // Wrap the config with the path spec information
128                 config = new PathParamServerEndpointConfig(config,wspathSpec,requestPath);
129             }
130             return new EndpointInstance(endpoint,config,metadata);
131         }
132         catch (InstantiationException e)
133         {
134             LOG.debug("Unable to create websocket: " + config.getEndpointClass().getName(),e);
135             return null;
136         }
137     }
138 
139     @Override
140     public String toString()
141     {
142         return String.format("%s[metadata=%s]",this.getClass().getName(),metadata);
143     }
144 }