Skip to content

Package: ServerEndpointConfig$Builder

ServerEndpointConfig$Builder

nameinstructionbranchcomplexitylinemethod
ServerEndpointConfig.Builder()
M: 15 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 6 C: 0
0%
M: 1 C: 0
0%
ServerEndpointConfig.Builder(Class, String)
M: 39 C: 0
0%
M: 6 C: 0
0%
M: 4 C: 0
0%
M: 12 C: 0
0%
M: 1 C: 0
0%
build()
M: 18 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
configurator(ServerEndpointConfig.Configurator)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
create(Class, String)
M: 6 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
decoders(List)
M: 11 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
encoders(List)
M: 11 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
extensions(List)
M: 11 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
subprotocols(List)
M: 11 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*
2: * Copyright (c) 2018, 2021 Oracle and/or its affiliates and others.
3: * All rights reserved.
4: *
5: * This program and the accompanying materials are made available under the
6: * terms of the Eclipse Public License v. 2.0, which is available at
7: * http://www.eclipse.org/legal/epl-2.0.
8: *
9: * This Source Code may also be made available under the following Secondary
10: * Licenses when the conditions for such availability set forth in the
11: * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
12: * version 2 with the GNU Classpath Exception, which is available at
13: * https://www.gnu.org/software/classpath/license.html.
14: *
15: * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
16: */
17:
18: package jakarta.websocket.server;
19:
20: import java.util.ArrayList;
21: import java.util.Collections;
22: import java.util.List;
23: import java.util.ServiceLoader;
24: import jakarta.websocket.Decoder;
25: import jakarta.websocket.Encoder;
26: import jakarta.websocket.EndpointConfig;
27: import jakarta.websocket.Extension;
28: import jakarta.websocket.HandshakeResponse;
29:
30: /**
31: * The ServerEndpointConfig is a special kind of endpoint configuration object that contains web socket configuration
32: * information specific only to server endpoints. For developers deploying programmatic endpoints, ServerEndpointConfig
33: * objects can be created using a {@link ServerEndpointConfig.Builder}. Certain configuration operations can be
34: * customized by providing a {@link ServerEndpointConfig.Configurator}
35: *
36: * @author dannycoward
37: */
38: public interface ServerEndpointConfig extends EndpointConfig {
39:
40: /**
41: * Returns the Class of the endpoint this configuration is configuring. If the endpoint is an annotated endpoint,
42: * the value is the class of the Java class annotated with @ServerEndpoint. if the endpoint is a programmatic, the
43: * value is the class of the subclass of Endpoint.
44: *
45: * @return the class of the endpoint, annotated or programmatic.
46: */
47: Class<?> getEndpointClass();
48:
49: /**
50: * Return the path for this endpoint configuration. The path is the URI or URI-template (level 1) relative to the
51: * websocket root of the server to which the endpoint using this configuration will be mapped. The path is always
52: * non-null and always begins with a leading "/".
53: *
54: * @return the relative path for this configuration.
55: */
56: String getPath();
57:
58: /**
59: * Return the websocket subprotocols configured.
60: *
61: * @return the list of subprotocols, the empty list if none
62: */
63: List<String> getSubprotocols();
64:
65: /**
66: * Return the websocket extensions configured.
67: *
68: * @return the list of extensions, the empty list if none.
69: */
70: List<Extension> getExtensions();
71:
72: /**
73: * Return the {@link ServerEndpointConfig.Configurator} this configuration is using. If none was set by calling
74: * {@link ServerEndpointConfig.Builder#configurator(jakarta.websocket.server.ServerEndpointConfig.Configurator) } this
75: * methods returns the platform default configurator.
76: *
77: * @return the configurator in use.
78: */
79: ServerEndpointConfig.Configurator getConfigurator();
80:
81: /**
82: * The ServerEndpointConfig.Configurator class may be extended by developers who want to provide custom
83: * configuration algorithms, such as intercepting the opening handshake, or providing arbitrary methods and
84: * algorithms that can be accessed from each endpoint instance configured with this configurator.
85: *
86: * The implementation must provide a platform default configurator loading using the service loader.
87: */
88: public class Configurator {
89: private ServerEndpointConfig.Configurator containerDefaultConfigurator;
90:
91: static ServerEndpointConfig.Configurator fetchContainerDefaultConfigurator() {
92: for (ServerEndpointConfig.Configurator impl : ServiceLoader
93: .load(jakarta.websocket.server.ServerEndpointConfig.Configurator.class)) {
94: return impl;
95: }
96: throw new RuntimeException("Cannot load platform configurator");
97: }
98:
99: /**
100: * Return the platform default configurator.
101: *
102: * @return the platform default configurator
103: */
104: public ServerEndpointConfig.Configurator getContainerDefaultConfigurator() {
105: if (this.containerDefaultConfigurator == null) {
106: this.containerDefaultConfigurator = fetchContainerDefaultConfigurator();
107: }
108: return this.containerDefaultConfigurator;
109:
110: }
111:
112: /**
113: * Return the subprotocol the server endpoint has chosen from the requested list supplied by a client who wishes
114: * to connect, or none if there wasn't one this server endpoint liked. See
115: * <a href="http://tools.ietf.org/html/rfc6455#section-4.2.2">Sending the Server's Opening Handshake</a>.
116: * Subclasses may provide custom algorithms based on other factors.
117: *
118: * <p>
119: * The default platform implementation of this method returns the first subprotocol in the list sent by the
120: * client that the server supports, or the empty string if there isn't one.
121: *
122: * @param requested the requested subprotocols from the client endpoint
123: * @param supported the subprotocols supported by the server endpoint
124: * @return the negotiated subprotocol or the empty string if there isn't one.
125: */
126: public String getNegotiatedSubprotocol(List<String> supported, List<String> requested) {
127: return this.getContainerDefaultConfigurator().getNegotiatedSubprotocol(supported, requested);
128: }
129:
130: /**
131: * Return the ordered list of extensions that t server endpoint will support given the requested extension list
132: * passed in, the empty list if none. See <a href="http://tools.ietf.org/html/rfc6455#section-9.1">Negotiating
133: * Extensions</a>
134: *
135: * <p>
136: * The default platform implementation of this method returns a list containing all of the requested extensions
137: * passed to this method that it supports, using the order in the requested extensions, the empty list if none.
138: *
139: * @param installed the installed extensions on the implementation.
140: * @param requested the requested extensions, in the order they were requested by the client
141: * @return the list of extensions negotiated, the empty list if none.
142: */
143: public List<Extension> getNegotiatedExtensions(List<Extension> installed, List<Extension> requested) {
144: return this.getContainerDefaultConfigurator().getNegotiatedExtensions(installed, requested);
145: }
146:
147: /**
148: * Check the value of the Origin header (<a href="http://tools.ietf.org/html/rfc6454">See Origin Header</a>) the
149: * client passed during the opening handshake.
150: *
151: * <p>
152: * The platform default implementation of this method makes a check of the validity of the Origin header sent
153: * along with the opening handshake following the recommendation at:
154: * <a href="http://tools.ietf.org/html/rfc6455#section-4.2">Sending the Server's Opening Handshake</a>.
155: *
156: * @param originHeaderValue the value of the origin header passed by the client.
157: * @return whether the check passed or not
158: */
159: public boolean checkOrigin(String originHeaderValue) {
160: return this.getContainerDefaultConfigurator().checkOrigin(originHeaderValue);
161: }
162:
163: /**
164: * Called by the container after it has formulated a handshake response resulting from a well-formed handshake
165: * request. The container has already checked that this configuration has a matching URI, determined the
166: * validity of the origin using the checkOrigin method, and filled out the negotiated subprotocols and
167: * extensions based on this configuration. Custom configurations may override this method in order to inspect
168: * the request parameters and modify the handshake response that the server has formulated. and the URI checking
169: * also.
170: *
171: * <p>
172: * If the developer does not override this method, no further modification of the request and response are made
173: * by the implementation.
174: *
175: * @param sec the configuration object involved in the handshake
176: * @param request the opening handshake request.
177: * @param response the proposed opening handshake response
178: */
179: public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
180: // nothing.
181: }
182:
183: /**
184: * This method is called by the container each time a new client connects to the logical endpoint this
185: * configurator configures. Developers may override this method to control instantiation of endpoint instances
186: * in order to customize the initialization of the endpoint instance, or manage them in some other way. If the
187: * developer overrides this method, services like dependency injection that are otherwise supported, for
188: * example, when the implementation is part of the Java EE platform may not be available. The platform default
189: * implementation of this method returns a new endpoint instance per call, thereby ensuring that there is one
190: * endpoint instance per client, the default deployment cardinality.
191: *
192: * @param endpointClass the class of the endpoint
193: * @param <T> the type of the endpoint
194: * @return an instance of the endpoint that will handle all interactions from a new client.
195: * @throws InstantiationException if there was an error producing the endpoint instance.
196: */
197: public <T> T getEndpointInstance(Class<T> endpointClass) throws InstantiationException {
198: return this.getContainerDefaultConfigurator().getEndpointInstance(endpointClass);
199: }
200:
201: }
202:
203: /**
204: * The ServerEndpointConfig.Builder is a class used for creating {@link ServerEndpointConfig.Builder} objects for
205: * the purposes of deploying a server endpoint.
206: *
207: * <p>
208: * Here are some examples:
209: *
210: * <p>
211: * Building a plain configuration for an endpoint with just a path.
212: *
213: * <pre>
214: * <code>
215: * ServerEndpointConfig config = ServerEndpointConfig.Builder.create(ProgrammaticEndpoint.class, "/foo").build();
216: * </code>
217: * </pre>
218: *
219: * <p>
220: * Building a configuration with no subprotocols and a custom configurator.
221: *
222: * <pre>
223: * <code>
224: * ServerEndpointConfig config = ServerEndpointConfig.Builder.create(ProgrammaticEndpoint.class, "/bar")
225: * .subprotocols(subprotocols)
226: * .configurator(new MyServerConfigurator())
227: * .build();
228: * </code>
229: * </pre>
230: *
231: * @author dannycoward
232: */
233: public final class Builder {
234: private String path;
235: private Class<?> endpointClass;
236: private List<String> subprotocols = Collections.emptyList();
237: private List<Extension> extensions = Collections.emptyList();
238: private List<Class<? extends Encoder>> encoders = Collections.emptyList();
239: private List<Class<? extends Decoder>> decoders = Collections.emptyList();
240: private ServerEndpointConfig.Configurator serverEndpointConfigurator;
241:
242: /**
243: * Creates the builder with the mandatory information of the endpoint class (programmatic or annotated), the
244: * relative URI or URI-template to use, and with no subprotocols, extensions, encoders, decoders or custom
245: * configurator.
246: *
247: * @param endpointClass the class of the endpoint to configure
248: * @param path The URI or URI template where the endpoint will be deployed. A trailing "/" will be
249: * ignored and the path must begin with /.
250: * @return a new instance of ServerEndpointConfig.Builder
251: */
252: public static Builder create(Class<?> endpointClass, String path) {
253: return new Builder(endpointClass, path);
254: }
255:
256: // only one way to build them
257: private Builder() {
258:
259: }
260:
261: /**
262: * Builds the configuration object using the current attributes that have been set on this builder object.
263: *
264: * @return a new ServerEndpointConfig object.
265: */
266: public ServerEndpointConfig build() {
267: return new DefaultServerEndpointConfig(this.endpointClass, this.path, this.subprotocols, this.extensions,
268: this.encoders, this.decoders, this.serverEndpointConfigurator);
269: }
270:
271: private Builder(Class<?> endpointClass, String path) {
272:• if (endpointClass == null) {
273: throw new IllegalArgumentException("endpointClass cannot be null");
274: }
275: this.endpointClass = endpointClass;
276:• if (path == null || !path.startsWith("/")) {
277: throw new IllegalStateException("Path cannot be null and must begin with /");
278: }
279: this.path = path;
280: }
281:
282: /**
283: * Sets the list of encoder implementation classes for this builder.
284: *
285: * @param encoders the encoders
286: * @return this builder instance
287: */
288: public ServerEndpointConfig.Builder encoders(List<Class<? extends Encoder>> encoders) {
289:• this.encoders = (encoders == null) ? new ArrayList<>() : encoders;
290: return this;
291: }
292:
293: /**
294: * Sets the decoder implementation classes to use in the configuration.
295: *
296: * @param decoders the decoders
297: * @return this builder instance.
298: */
299: public ServerEndpointConfig.Builder decoders(List<Class<? extends Decoder>> decoders) {
300:• this.decoders = (decoders == null) ? new ArrayList<>() : decoders;
301: return this;
302: }
303:
304: /**
305: * Sets the subprotocols to use in the configuration.
306: *
307: * @param subprotocols the subprotocols.
308: * @return this builder instance
309: */
310: public ServerEndpointConfig.Builder subprotocols(List<String> subprotocols) {
311:• this.subprotocols = (subprotocols == null) ? new ArrayList<>() : subprotocols;
312: return this;
313: }
314:
315: /**
316: * Sets the extensions to use in the configuration.
317: *
318: * @param extensions the extensions to use.
319: * @return this builder instance.
320: */
321: public ServerEndpointConfig.Builder extensions(List<Extension> extensions) {
322:• this.extensions = (extensions == null) ? new ArrayList<>() : extensions;
323: return this;
324: }
325:
326: /**
327: * Sets the custom configurator to use on the configuration object built by this builder.
328: *
329: * @param serverEndpointConfigurator the configurator
330: * @return this builder instance
331: */
332: public ServerEndpointConfig.Builder configurator(ServerEndpointConfig.Configurator serverEndpointConfigurator) {
333: this.serverEndpointConfigurator = serverEndpointConfigurator;
334: return this;
335: }
336:
337: }
338:
339: }