1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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.Collections;
24 import java.util.List;
25 import java.util.Map;
26
27 import javax.websocket.Extension;
28 import javax.websocket.Extension.Parameter;
29 import javax.websocket.server.ServerEndpointConfig;
30 import javax.websocket.server.ServerEndpointConfig.Configurator;
31
32 import org.eclipse.jetty.http.pathmap.PathSpec;
33 import org.eclipse.jetty.http.pathmap.UriTemplatePathSpec;
34 import org.eclipse.jetty.util.StringUtil;
35 import org.eclipse.jetty.util.log.Log;
36 import org.eclipse.jetty.util.log.Logger;
37 import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
38 import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
39 import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
40 import org.eclipse.jetty.websocket.jsr356.JsrExtension;
41 import org.eclipse.jetty.websocket.jsr356.endpoints.EndpointInstance;
42 import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
43 import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
44 import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
45
46 public class JsrCreator implements WebSocketCreator
47 {
48 public static final String PROP_REMOTE_ADDRESS = "javax.websocket.endpoint.remoteAddress";
49 public static final String PROP_LOCAL_ADDRESS = "javax.websocket.endpoint.localAddress";
50 public static final String PROP_LOCALES = "javax.websocket.upgrade.locales";
51 private static final Logger LOG = Log.getLogger(JsrCreator.class);
52 private final WebSocketContainerScope containerScope;
53 private final ServerEndpointMetadata metadata;
54 private final ExtensionFactory extensionFactory;
55
56 public JsrCreator(WebSocketContainerScope containerScope, ServerEndpointMetadata metadata, ExtensionFactory extensionFactory)
57 {
58 this.containerScope = containerScope;
59 this.metadata = metadata;
60 this.extensionFactory = extensionFactory;
61 }
62
63 @Override
64 public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp)
65 {
66 JsrHandshakeRequest hsreq = new JsrHandshakeRequest(req);
67 JsrHandshakeResponse hsresp = new JsrHandshakeResponse(resp);
68
69
70 ServerEndpointConfig config = metadata.getConfig();
71
72
73
74 config = new BasicServerEndpointConfig(containerScope, config);
75
76
77
78
79
80 Map<String, Object> userProperties = config.getUserProperties();
81 userProperties.put(PROP_LOCAL_ADDRESS,req.getLocalSocketAddress());
82 userProperties.put(PROP_REMOTE_ADDRESS,req.getRemoteSocketAddress());
83 userProperties.put(PROP_LOCALES,Collections.list(req.getLocales()));
84
85
86 ServerEndpointConfig.Configurator configurator = config.getConfigurator();
87
88
89 configurator.modifyHandshake(config,hsreq,hsresp);
90
91
92 if (!configurator.checkOrigin(req.getOrigin()))
93 {
94 try
95 {
96 resp.sendForbidden("Origin mismatch");
97 }
98 catch (IOException e)
99 {
100 if (LOG.isDebugEnabled())
101 LOG.debug("Unable to send error response",e);
102 }
103 return null;
104 }
105
106
107 List<String> supported = config.getSubprotocols();
108 List<String> requested = req.getSubProtocols();
109 String subprotocol = configurator.getNegotiatedSubprotocol(supported,requested);
110 if (StringUtil.isNotBlank(subprotocol))
111 {
112 resp.setAcceptedSubProtocol(subprotocol);
113 }
114
115
116 List<Extension> installedExts = new ArrayList<>();
117 for (String extName : extensionFactory.getAvailableExtensions().keySet())
118 {
119 installedExts.add(new JsrExtension(extName));
120 }
121 List<Extension> requestedExts = new ArrayList<>();
122 for (ExtensionConfig reqCfg : req.getExtensions())
123 {
124 requestedExts.add(new JsrExtension(reqCfg));
125 }
126 List<Extension> usedExts = configurator.getNegotiatedExtensions(installedExts,requestedExts);
127 List<ExtensionConfig> configs = new ArrayList<>();
128 if (usedExts != null)
129 {
130 for (Extension used : usedExts)
131 {
132 ExtensionConfig ecfg = new ExtensionConfig(used.getName());
133 for (Parameter param : used.getParameters())
134 {
135 ecfg.setParameter(param.getName(),param.getValue());
136 }
137 configs.add(ecfg);
138 }
139 }
140 resp.setExtensions(configs);
141
142
143 try
144 {
145 Class<?> endpointClass = config.getEndpointClass();
146 Configurator configr = config.getConfigurator();
147 Object endpoint = configr.getEndpointInstance(endpointClass);
148
149
150 PathSpec pathSpec = hsreq.getRequestPathSpec();
151 if (pathSpec instanceof UriTemplatePathSpec)
152 {
153
154 UriTemplatePathSpec wspathSpec = (UriTemplatePathSpec)pathSpec;
155 String requestPath = req.getRequestPath();
156
157 config = new PathParamServerEndpointConfig(containerScope,config,wspathSpec,requestPath);
158 }
159 return new EndpointInstance(endpoint,config,metadata);
160 }
161 catch (InstantiationException e)
162 {
163 if (LOG.isDebugEnabled())
164 LOG.debug("Unable to create websocket: " + config.getEndpointClass().getName(),e);
165 return null;
166 }
167 }
168
169 @Override
170 public String toString()
171 {
172 return String.format("%s[metadata=%s]",this.getClass().getName(),metadata);
173 }
174 }