1 /*
2  * JBoss, Home of Professional Open Source.
3  * Copyright 2014 Red Hat, Inc., and individual contributors
4  * as indicated by the @author tags.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  */

18
19 package io.undertow.websockets.jsr;
20
21 import io.undertow.server.XnioByteBufferPool;
22 import io.undertow.websockets.extensions.ExtensionHandshake;
23 import io.undertow.connector.ByteBufferPool;
24 import org.xnio.Pool;
25 import org.xnio.XnioWorker;
26
27 import javax.websocket.server.ServerEndpointConfig;
28 import java.nio.ByteBuffer;
29 import java.util.ArrayList;
30 import java.util.Collection;
31 import java.util.List;
32 import java.util.function.Supplier;
33
34 /**
35  * Web socket deployment information
36  *
37  * @author Stuart Douglas
38  */

39 public class WebSocketDeploymentInfo implements Cloneable {
40
41     public static final String ATTRIBUTE_NAME = "io.undertow.websockets.jsr.WebSocketDeploymentInfo";
42
43     private Supplier<XnioWorker> worker = new Supplier<XnioWorker>() {
44
45         volatile XnioWorker worker;
46
47         @Override
48         public XnioWorker get() {
49             if(worker != null) {
50                 return worker;
51             }
52             return worker = UndertowContainerProvider.getDefaultContainer().getXnioWorker();
53         }
54     };
55     private ByteBufferPool buffers;
56     private boolean dispatchToWorkerThread = false;
57     private final List<Class<?>> annotatedEndpoints = new ArrayList<>();
58     private final List<ServerEndpointConfig> programaticEndpoints = new ArrayList<>();
59     private final List<ContainerReadyListener> containerReadyListeners = new ArrayList<>();
60     private final List<ExtensionHandshake> extensions = new ArrayList<>();
61     private String clientBindAddress = null;
62     private WebSocketReconnectHandler reconnectHandler;
63
64     public Supplier<XnioWorker> getWorker() {
65         return worker;
66     }
67
68     public WebSocketDeploymentInfo setWorker(Supplier<XnioWorker> worker) {
69         this.worker = worker;
70         return this;
71     }
72
73     public WebSocketDeploymentInfo setWorker(XnioWorker worker) {
74         this.worker = new Supplier<XnioWorker>() {
75             @Override
76             public XnioWorker get() {
77                 return worker;
78             }
79         };
80         return this;
81     }
82
83     public ByteBufferPool getBuffers() {
84         return buffers;
85     }
86
87     @Deprecated
88     public WebSocketDeploymentInfo setBuffers(Pool<ByteBuffer> buffers) {
89         return setBuffers(new XnioByteBufferPool(buffers));
90     }
91
92     public WebSocketDeploymentInfo setBuffers(ByteBufferPool buffers) {
93         this.buffers = buffers;
94         return this;
95     }
96
97     public WebSocketDeploymentInfo addEndpoint(final Class<?> annotated) {
98         this.annotatedEndpoints.add(annotated);
99         return this;
100     }
101
102     public WebSocketDeploymentInfo addAnnotatedEndpoints(final Collection<Class<?>> annotatedEndpoints) {
103         this.annotatedEndpoints.addAll(annotatedEndpoints);
104         return this;
105     }
106
107     public WebSocketDeploymentInfo addEndpoint(final ServerEndpointConfig endpoint) {
108         this.programaticEndpoints.add(endpoint);
109         return this;
110     }
111
112     public WebSocketDeploymentInfo addProgramaticEndpoints(final Collection<ServerEndpointConfig> programaticEndpoints) {
113         this.programaticEndpoints.addAll(programaticEndpoints);
114         return this;
115     }
116
117     public List<Class<?>> getAnnotatedEndpoints() {
118         return annotatedEndpoints;
119     }
120
121     public List<ServerEndpointConfig> getProgramaticEndpoints() {
122         return programaticEndpoints;
123     }
124
125     void containerReady(ServerWebSocketContainer container) {
126         for(ContainerReadyListener listener : containerReadyListeners) {
127             listener.ready(container);
128         }
129     }
130
131     public WebSocketDeploymentInfo addListener(final ContainerReadyListener listener) {
132         containerReadyListeners.add(listener);
133         return this;
134     }
135
136     public WebSocketDeploymentInfo addListeners(final Collection<ContainerReadyListener> listeners) {
137         containerReadyListeners.addAll(listeners);
138         return this;
139     }
140
141     public List<ContainerReadyListener> getListeners() {
142         return containerReadyListeners;
143     }
144
145     public boolean isDispatchToWorkerThread() {
146         return dispatchToWorkerThread;
147     }
148
149     public WebSocketDeploymentInfo setDispatchToWorkerThread(boolean dispatchToWorkerThread) {
150         this.dispatchToWorkerThread = dispatchToWorkerThread;
151         return this;
152     }
153
154     public interface ContainerReadyListener {
155         void ready(ServerWebSocketContainer container);
156     }
157
158     /**
159      * Add a new WebSocket Extension into this deployment info.
160      *
161      * @param extension a new {@code ExtensionHandshake} instance
162      * @return          current deployment info
163      */

164     public WebSocketDeploymentInfo addExtension(final ExtensionHandshake extension) {
165         if (null != extension) {
166             this.extensions.add(extension);
167         }
168         return this;
169     }
170
171     public WebSocketDeploymentInfo addExtensions(final Collection<ExtensionHandshake> extensions) {
172         this.extensions.addAll(extensions);
173         return this;
174     }
175
176     /**
177      * @return list of extensions available for this deployment info
178      */

179     public List<ExtensionHandshake> getExtensions() {
180         return extensions;
181     }
182
183     public String getClientBindAddress() {
184         return clientBindAddress;
185     }
186
187     public WebSocketDeploymentInfo setClientBindAddress(String clientBindAddress) {
188         this.clientBindAddress = clientBindAddress;
189         return this;
190     }
191
192     public WebSocketReconnectHandler getReconnectHandler() {
193         return reconnectHandler;
194     }
195
196     public WebSocketDeploymentInfo setReconnectHandler(WebSocketReconnectHandler reconnectHandler) {
197         this.reconnectHandler = reconnectHandler;
198         return this;
199     }
200
201     @Override
202     public WebSocketDeploymentInfo clone() {
203         return new WebSocketDeploymentInfo()
204                 .setWorker(this.worker)
205                 .setBuffers(this.buffers)
206                 .setDispatchToWorkerThread(this.dispatchToWorkerThread)
207                 .addAnnotatedEndpoints(this.annotatedEndpoints)
208                 .addProgramaticEndpoints(this.programaticEndpoints)
209                 .addListeners(this.containerReadyListeners)
210                 .addExtensions(this.extensions)
211                 .setClientBindAddress(this.clientBindAddress)
212                 .setReconnectHandler(this.reconnectHandler)
213         ;
214     }
215
216 }
217