xref: /unit/src/java/javax/websocket/server/ServerEndpointConfig.java (revision 1157:7ae152bda303)
1*1157Smax.romanov@nginx.com /*
2*1157Smax.romanov@nginx.com  * Licensed to the Apache Software Foundation (ASF) under one or more
3*1157Smax.romanov@nginx.com  * contributor license agreements.  See the NOTICE file distributed with
4*1157Smax.romanov@nginx.com  * this work for additional information regarding copyright ownership.
5*1157Smax.romanov@nginx.com  * The ASF licenses this file to You under the Apache License, Version 2.0
6*1157Smax.romanov@nginx.com  * (the "License"); you may not use this file except in compliance with
7*1157Smax.romanov@nginx.com  * the License.  You may obtain a copy of the License at
8*1157Smax.romanov@nginx.com  *
9*1157Smax.romanov@nginx.com  *     http://www.apache.org/licenses/LICENSE-2.0
10*1157Smax.romanov@nginx.com  *
11*1157Smax.romanov@nginx.com  * Unless required by applicable law or agreed to in writing, software
12*1157Smax.romanov@nginx.com  * distributed under the License is distributed on an "AS IS" BASIS,
13*1157Smax.romanov@nginx.com  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*1157Smax.romanov@nginx.com  * See the License for the specific language governing permissions and
15*1157Smax.romanov@nginx.com  * limitations under the License.
16*1157Smax.romanov@nginx.com  */
17*1157Smax.romanov@nginx.com package javax.websocket.server;
18*1157Smax.romanov@nginx.com 
19*1157Smax.romanov@nginx.com import java.util.Collections;
20*1157Smax.romanov@nginx.com import java.util.Iterator;
21*1157Smax.romanov@nginx.com import java.util.List;
22*1157Smax.romanov@nginx.com import java.util.ServiceLoader;
23*1157Smax.romanov@nginx.com 
24*1157Smax.romanov@nginx.com import javax.websocket.Decoder;
25*1157Smax.romanov@nginx.com import javax.websocket.Encoder;
26*1157Smax.romanov@nginx.com import javax.websocket.EndpointConfig;
27*1157Smax.romanov@nginx.com import javax.websocket.Extension;
28*1157Smax.romanov@nginx.com import javax.websocket.HandshakeResponse;
29*1157Smax.romanov@nginx.com 
30*1157Smax.romanov@nginx.com /**
31*1157Smax.romanov@nginx.com  * Provides configuration information for WebSocket endpoints published to a
32*1157Smax.romanov@nginx.com  * server. Applications may provide their own implementation or use
33*1157Smax.romanov@nginx.com  * {@link Builder}.
34*1157Smax.romanov@nginx.com  */
35*1157Smax.romanov@nginx.com public interface ServerEndpointConfig extends EndpointConfig {
36*1157Smax.romanov@nginx.com 
getEndpointClass()37*1157Smax.romanov@nginx.com     Class<?> getEndpointClass();
38*1157Smax.romanov@nginx.com 
39*1157Smax.romanov@nginx.com     /**
40*1157Smax.romanov@nginx.com      * Returns the path at which this WebSocket server endpoint has been
41*1157Smax.romanov@nginx.com      * registered. It may be a path or a level 0 URI template.
42*1157Smax.romanov@nginx.com      * @return The registered path
43*1157Smax.romanov@nginx.com      */
getPath()44*1157Smax.romanov@nginx.com     String getPath();
45*1157Smax.romanov@nginx.com 
getSubprotocols()46*1157Smax.romanov@nginx.com     List<String> getSubprotocols();
47*1157Smax.romanov@nginx.com 
getExtensions()48*1157Smax.romanov@nginx.com     List<Extension> getExtensions();
49*1157Smax.romanov@nginx.com 
getConfigurator()50*1157Smax.romanov@nginx.com     Configurator getConfigurator();
51*1157Smax.romanov@nginx.com 
52*1157Smax.romanov@nginx.com 
53*1157Smax.romanov@nginx.com     public final class Builder {
54*1157Smax.romanov@nginx.com 
create( Class<?> endpointClass, String path)55*1157Smax.romanov@nginx.com         public static Builder create(
56*1157Smax.romanov@nginx.com                 Class<?> endpointClass, String path) {
57*1157Smax.romanov@nginx.com             return new Builder(endpointClass, path);
58*1157Smax.romanov@nginx.com         }
59*1157Smax.romanov@nginx.com 
60*1157Smax.romanov@nginx.com 
61*1157Smax.romanov@nginx.com         private final Class<?> endpointClass;
62*1157Smax.romanov@nginx.com         private final String path;
63*1157Smax.romanov@nginx.com         private List<Class<? extends Encoder>> encoders =
64*1157Smax.romanov@nginx.com                 Collections.emptyList();
65*1157Smax.romanov@nginx.com         private List<Class<? extends Decoder>> decoders =
66*1157Smax.romanov@nginx.com                 Collections.emptyList();
67*1157Smax.romanov@nginx.com         private List<String> subprotocols = Collections.emptyList();
68*1157Smax.romanov@nginx.com         private List<Extension> extensions = Collections.emptyList();
69*1157Smax.romanov@nginx.com         private Configurator configurator =
70*1157Smax.romanov@nginx.com                 Configurator.fetchContainerDefaultConfigurator();
71*1157Smax.romanov@nginx.com 
72*1157Smax.romanov@nginx.com 
Builder(Class<?> endpointClass, String path)73*1157Smax.romanov@nginx.com         private Builder(Class<?> endpointClass,
74*1157Smax.romanov@nginx.com                 String path) {
75*1157Smax.romanov@nginx.com             this.endpointClass = endpointClass;
76*1157Smax.romanov@nginx.com             this.path = path;
77*1157Smax.romanov@nginx.com         }
78*1157Smax.romanov@nginx.com 
build()79*1157Smax.romanov@nginx.com         public ServerEndpointConfig build() {
80*1157Smax.romanov@nginx.com             return new DefaultServerEndpointConfig(endpointClass, path,
81*1157Smax.romanov@nginx.com                     subprotocols, extensions, encoders, decoders, configurator);
82*1157Smax.romanov@nginx.com         }
83*1157Smax.romanov@nginx.com 
84*1157Smax.romanov@nginx.com 
encoders( List<Class<? extends Encoder>> encoders)85*1157Smax.romanov@nginx.com         public Builder encoders(
86*1157Smax.romanov@nginx.com                 List<Class<? extends Encoder>> encoders) {
87*1157Smax.romanov@nginx.com             if (encoders == null || encoders.size() == 0) {
88*1157Smax.romanov@nginx.com                 this.encoders = Collections.emptyList();
89*1157Smax.romanov@nginx.com             } else {
90*1157Smax.romanov@nginx.com                 this.encoders = Collections.unmodifiableList(encoders);
91*1157Smax.romanov@nginx.com             }
92*1157Smax.romanov@nginx.com             return this;
93*1157Smax.romanov@nginx.com         }
94*1157Smax.romanov@nginx.com 
95*1157Smax.romanov@nginx.com 
decoders( List<Class<? extends Decoder>> decoders)96*1157Smax.romanov@nginx.com         public Builder decoders(
97*1157Smax.romanov@nginx.com                 List<Class<? extends Decoder>> decoders) {
98*1157Smax.romanov@nginx.com             if (decoders == null || decoders.size() == 0) {
99*1157Smax.romanov@nginx.com                 this.decoders = Collections.emptyList();
100*1157Smax.romanov@nginx.com             } else {
101*1157Smax.romanov@nginx.com                 this.decoders = Collections.unmodifiableList(decoders);
102*1157Smax.romanov@nginx.com             }
103*1157Smax.romanov@nginx.com             return this;
104*1157Smax.romanov@nginx.com         }
105*1157Smax.romanov@nginx.com 
106*1157Smax.romanov@nginx.com 
subprotocols( List<String> subprotocols)107*1157Smax.romanov@nginx.com         public Builder subprotocols(
108*1157Smax.romanov@nginx.com                 List<String> subprotocols) {
109*1157Smax.romanov@nginx.com             if (subprotocols == null || subprotocols.size() == 0) {
110*1157Smax.romanov@nginx.com                 this.subprotocols = Collections.emptyList();
111*1157Smax.romanov@nginx.com             } else {
112*1157Smax.romanov@nginx.com                 this.subprotocols = Collections.unmodifiableList(subprotocols);
113*1157Smax.romanov@nginx.com             }
114*1157Smax.romanov@nginx.com             return this;
115*1157Smax.romanov@nginx.com         }
116*1157Smax.romanov@nginx.com 
117*1157Smax.romanov@nginx.com 
extensions( List<Extension> extensions)118*1157Smax.romanov@nginx.com         public Builder extensions(
119*1157Smax.romanov@nginx.com                 List<Extension> extensions) {
120*1157Smax.romanov@nginx.com             if (extensions == null || extensions.size() == 0) {
121*1157Smax.romanov@nginx.com                 this.extensions = Collections.emptyList();
122*1157Smax.romanov@nginx.com             } else {
123*1157Smax.romanov@nginx.com                 this.extensions = Collections.unmodifiableList(extensions);
124*1157Smax.romanov@nginx.com             }
125*1157Smax.romanov@nginx.com             return this;
126*1157Smax.romanov@nginx.com         }
127*1157Smax.romanov@nginx.com 
128*1157Smax.romanov@nginx.com 
configurator(Configurator serverEndpointConfigurator)129*1157Smax.romanov@nginx.com         public Builder configurator(Configurator serverEndpointConfigurator) {
130*1157Smax.romanov@nginx.com             if (serverEndpointConfigurator == null) {
131*1157Smax.romanov@nginx.com                 this.configurator = Configurator.fetchContainerDefaultConfigurator();
132*1157Smax.romanov@nginx.com             } else {
133*1157Smax.romanov@nginx.com                 this.configurator = serverEndpointConfigurator;
134*1157Smax.romanov@nginx.com             }
135*1157Smax.romanov@nginx.com             return this;
136*1157Smax.romanov@nginx.com         }
137*1157Smax.romanov@nginx.com     }
138*1157Smax.romanov@nginx.com 
139*1157Smax.romanov@nginx.com 
140*1157Smax.romanov@nginx.com     public class Configurator {
141*1157Smax.romanov@nginx.com 
142*1157Smax.romanov@nginx.com         private static volatile Configurator defaultImpl = null;
143*1157Smax.romanov@nginx.com         private static final Object defaultImplLock = new Object();
144*1157Smax.romanov@nginx.com 
145*1157Smax.romanov@nginx.com         private static final String DEFAULT_IMPL_CLASSNAME =
146*1157Smax.romanov@nginx.com                 "nginx.unit.websocket.server.DefaultServerEndpointConfigurator";
147*1157Smax.romanov@nginx.com 
setDefault(Configurator def)148*1157Smax.romanov@nginx.com         public static void setDefault(Configurator def) {
149*1157Smax.romanov@nginx.com             synchronized (defaultImplLock) {
150*1157Smax.romanov@nginx.com                 defaultImpl = def;
151*1157Smax.romanov@nginx.com             }
152*1157Smax.romanov@nginx.com         }
153*1157Smax.romanov@nginx.com 
fetchContainerDefaultConfigurator()154*1157Smax.romanov@nginx.com         static Configurator fetchContainerDefaultConfigurator() {
155*1157Smax.romanov@nginx.com             if (defaultImpl == null) {
156*1157Smax.romanov@nginx.com                 synchronized (defaultImplLock) {
157*1157Smax.romanov@nginx.com                     if (defaultImpl == null) {
158*1157Smax.romanov@nginx.com                         defaultImpl = loadDefault();
159*1157Smax.romanov@nginx.com                     }
160*1157Smax.romanov@nginx.com                 }
161*1157Smax.romanov@nginx.com             }
162*1157Smax.romanov@nginx.com             return defaultImpl;
163*1157Smax.romanov@nginx.com         }
164*1157Smax.romanov@nginx.com 
165*1157Smax.romanov@nginx.com 
loadDefault()166*1157Smax.romanov@nginx.com         private static Configurator loadDefault() {
167*1157Smax.romanov@nginx.com             Configurator result = null;
168*1157Smax.romanov@nginx.com 
169*1157Smax.romanov@nginx.com             ServiceLoader<Configurator> serviceLoader =
170*1157Smax.romanov@nginx.com                     ServiceLoader.load(Configurator.class);
171*1157Smax.romanov@nginx.com 
172*1157Smax.romanov@nginx.com             Iterator<Configurator> iter = serviceLoader.iterator();
173*1157Smax.romanov@nginx.com             while (result == null && iter.hasNext()) {
174*1157Smax.romanov@nginx.com                 result = iter.next();
175*1157Smax.romanov@nginx.com             }
176*1157Smax.romanov@nginx.com 
177*1157Smax.romanov@nginx.com             // Fall-back. Also used by unit tests
178*1157Smax.romanov@nginx.com             if (result == null) {
179*1157Smax.romanov@nginx.com                 try {
180*1157Smax.romanov@nginx.com                     @SuppressWarnings("unchecked")
181*1157Smax.romanov@nginx.com                     Class<Configurator> clazz =
182*1157Smax.romanov@nginx.com                             (Class<Configurator>) Class.forName(
183*1157Smax.romanov@nginx.com                                     DEFAULT_IMPL_CLASSNAME);
184*1157Smax.romanov@nginx.com                     result = clazz.getConstructor().newInstance();
185*1157Smax.romanov@nginx.com                 } catch (ReflectiveOperationException | IllegalArgumentException |
186*1157Smax.romanov@nginx.com                         SecurityException e) {
187*1157Smax.romanov@nginx.com                     // No options left. Just return null.
188*1157Smax.romanov@nginx.com                 }
189*1157Smax.romanov@nginx.com             }
190*1157Smax.romanov@nginx.com             return result;
191*1157Smax.romanov@nginx.com         }
192*1157Smax.romanov@nginx.com 
getNegotiatedSubprotocol(List<String> supported, List<String> requested)193*1157Smax.romanov@nginx.com         public String getNegotiatedSubprotocol(List<String> supported,
194*1157Smax.romanov@nginx.com                 List<String> requested) {
195*1157Smax.romanov@nginx.com             return fetchContainerDefaultConfigurator().getNegotiatedSubprotocol(supported, requested);
196*1157Smax.romanov@nginx.com         }
197*1157Smax.romanov@nginx.com 
getNegotiatedExtensions(List<Extension> installed, List<Extension> requested)198*1157Smax.romanov@nginx.com         public List<Extension> getNegotiatedExtensions(List<Extension> installed,
199*1157Smax.romanov@nginx.com                 List<Extension> requested) {
200*1157Smax.romanov@nginx.com             return fetchContainerDefaultConfigurator().getNegotiatedExtensions(installed, requested);
201*1157Smax.romanov@nginx.com         }
202*1157Smax.romanov@nginx.com 
checkOrigin(String originHeaderValue)203*1157Smax.romanov@nginx.com         public boolean checkOrigin(String originHeaderValue) {
204*1157Smax.romanov@nginx.com             return fetchContainerDefaultConfigurator().checkOrigin(originHeaderValue);
205*1157Smax.romanov@nginx.com         }
206*1157Smax.romanov@nginx.com 
modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response)207*1157Smax.romanov@nginx.com         public void modifyHandshake(ServerEndpointConfig sec,
208*1157Smax.romanov@nginx.com                 HandshakeRequest request, HandshakeResponse response) {
209*1157Smax.romanov@nginx.com             fetchContainerDefaultConfigurator().modifyHandshake(sec, request, response);
210*1157Smax.romanov@nginx.com         }
211*1157Smax.romanov@nginx.com 
getEndpointInstance(Class<T> clazz)212*1157Smax.romanov@nginx.com         public <T extends Object> T getEndpointInstance(Class<T> clazz)
213*1157Smax.romanov@nginx.com                 throws InstantiationException {
214*1157Smax.romanov@nginx.com             return fetchContainerDefaultConfigurator().getEndpointInstance(
215*1157Smax.romanov@nginx.com                     clazz);
216*1157Smax.romanov@nginx.com         }
217*1157Smax.romanov@nginx.com     }
218*1157Smax.romanov@nginx.com }
219