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