View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.websocket.jsr356.server;
20  
21  import java.util.ArrayList;
22  import java.util.List;
23  import java.util.concurrent.Executor;
24  
25  import javax.websocket.DeploymentException;
26  import javax.websocket.Endpoint;
27  import javax.websocket.server.ServerEndpoint;
28  import javax.websocket.server.ServerEndpointConfig;
29  
30  import org.eclipse.jetty.http.pathmap.UriTemplatePathSpec;
31  import org.eclipse.jetty.util.log.Log;
32  import org.eclipse.jetty.util.log.Logger;
33  import org.eclipse.jetty.websocket.common.WebSocketSession;
34  import org.eclipse.jetty.websocket.common.events.EventDriverFactory;
35  import org.eclipse.jetty.websocket.jsr356.ClientContainer;
36  import org.eclipse.jetty.websocket.jsr356.JsrSessionFactory;
37  import org.eclipse.jetty.websocket.jsr356.annotations.AnnotatedEndpointScanner;
38  import org.eclipse.jetty.websocket.jsr356.endpoints.EndpointInstance;
39  import org.eclipse.jetty.websocket.jsr356.metadata.EndpointMetadata;
40  import org.eclipse.jetty.websocket.server.MappedWebSocketCreator;
41  import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
42  
43  public class ServerContainer extends ClientContainer implements javax.websocket.server.ServerContainer
44  {
45      private static final Logger LOG = Log.getLogger(ServerContainer.class);
46  
47      private final MappedWebSocketCreator mappedCreator;
48      private final WebSocketServerFactory webSocketServerFactory;
49      private List<Class<?>> deferredEndpointClasses;
50      private List<ServerEndpointConfig> deferredEndpointConfigs;
51  
52      public ServerContainer(MappedWebSocketCreator creator, WebSocketServerFactory factory, Executor executor)
53      {
54          super(factory);
55          this.mappedCreator = creator;
56          this.webSocketServerFactory = factory;
57          EventDriverFactory eventDriverFactory = this.webSocketServerFactory.getEventDriverFactory();
58          eventDriverFactory.addImplementation(new JsrServerEndpointImpl());
59          eventDriverFactory.addImplementation(new JsrServerExtendsEndpointImpl());
60          this.webSocketServerFactory.addSessionFactory(new JsrSessionFactory(this));
61          addBean(webSocketServerFactory);
62      }
63      
64      public EndpointInstance newClientEndpointInstance(Object endpoint, ServerEndpointConfig config, String path)
65      {
66          EndpointMetadata metadata = getClientEndpointMetadata(endpoint.getClass(),config);
67          ServerEndpointConfig cec = config;
68          if (config == null)
69          {
70              if (metadata instanceof AnnotatedServerEndpointMetadata)
71              {
72                  cec = ((AnnotatedServerEndpointMetadata)metadata).getConfig();
73              }
74              else
75              {
76                  cec = new BasicServerEndpointConfig(this,endpoint.getClass(),path);
77              }
78          }
79          return new EndpointInstance(endpoint,cec,metadata);
80      }
81  
82      @Override
83      public void addEndpoint(Class<?> endpointClass) throws DeploymentException
84      {
85          if (isStarted() || isStarting())
86          {
87              ServerEndpointMetadata metadata = getServerEndpointMetadata(endpointClass,null);
88              addEndpoint(metadata);
89          }
90          else
91          {
92              if (deferredEndpointClasses == null)
93              {
94                  deferredEndpointClasses = new ArrayList<Class<?>>();
95              }
96              deferredEndpointClasses.add(endpointClass);
97          }
98      }
99  
100     private void addEndpoint(ServerEndpointMetadata metadata) throws DeploymentException
101     {
102         JsrCreator creator = new JsrCreator(this,metadata,webSocketServerFactory.getExtensionFactory());
103         mappedCreator.addMapping(new UriTemplatePathSpec(metadata.getPath()),creator);
104     }
105 
106     @Override
107     public void addEndpoint(ServerEndpointConfig config) throws DeploymentException
108     {
109         if (isStarted() || isStarting())
110         {
111             if (LOG.isDebugEnabled())
112             {
113                 LOG.debug("addEndpoint({}) path={} endpoint={}",config,config.getPath(),config.getEndpointClass());
114             }
115             ServerEndpointMetadata metadata = getServerEndpointMetadata(config.getEndpointClass(),config);
116             addEndpoint(metadata);
117         }
118         else
119         {
120             if (deferredEndpointConfigs == null)
121             {
122                 deferredEndpointConfigs = new ArrayList<ServerEndpointConfig>();
123             }
124             deferredEndpointConfigs.add(config);
125         }
126     }
127     
128     @Override
129     protected void doStart() throws Exception
130     {
131         // Proceed with Normal Startup
132         super.doStart();
133         
134         // Process Deferred Endpoints
135         if (deferredEndpointClasses != null)
136         {
137             for (Class<?> endpointClass : deferredEndpointClasses)
138             {
139                 addEndpoint(endpointClass);
140             }
141             deferredEndpointClasses.clear();
142         }
143         
144         if (deferredEndpointConfigs != null)
145         {
146             for (ServerEndpointConfig config : deferredEndpointConfigs)
147             {
148                 addEndpoint(config);
149             }
150             deferredEndpointConfigs.clear();
151         }
152     }
153 
154     public ServerEndpointMetadata getServerEndpointMetadata(final Class<?> endpoint, final ServerEndpointConfig config) throws DeploymentException
155     {
156         ServerEndpointMetadata metadata = null;
157 
158         ServerEndpoint anno = endpoint.getAnnotation(ServerEndpoint.class);
159         if (anno != null)
160         {
161             // Annotated takes precedence here
162             AnnotatedServerEndpointMetadata ametadata = new AnnotatedServerEndpointMetadata(this,endpoint,config);
163             AnnotatedEndpointScanner<ServerEndpoint, ServerEndpointConfig> scanner = new AnnotatedEndpointScanner<>(ametadata);
164             metadata = ametadata;
165             scanner.scan();
166         }
167         else if (Endpoint.class.isAssignableFrom(endpoint))
168         {
169             // extends Endpoint
170             @SuppressWarnings("unchecked")
171             Class<? extends Endpoint> eendpoint = (Class<? extends Endpoint>)endpoint;
172             metadata = new SimpleServerEndpointMetadata(eendpoint,config);
173         }
174         else
175         {
176             StringBuilder err = new StringBuilder();
177             err.append("Not a recognized websocket [");
178             err.append(endpoint.getName());
179             err.append("] does not extend @").append(ServerEndpoint.class.getName());
180             err.append(" or extend from ").append(Endpoint.class.getName());
181             throw new DeploymentException("Unable to identify as valid Endpoint: " + endpoint);
182         }
183 
184         return metadata;
185     }
186 
187     @Override
188     public long getDefaultAsyncSendTimeout()
189     {
190         return webSocketServerFactory.getPolicy().getAsyncWriteTimeout();
191     }
192 
193     @Override
194     public int getDefaultMaxBinaryMessageBufferSize()
195     {
196         return webSocketServerFactory.getPolicy().getMaxBinaryMessageSize();
197     }
198 
199     @Override
200     public long getDefaultMaxSessionIdleTimeout()
201     {
202         return webSocketServerFactory.getPolicy().getIdleTimeout();
203     }
204 
205     @Override
206     public int getDefaultMaxTextMessageBufferSize()
207     {
208         return webSocketServerFactory.getPolicy().getMaxTextMessageSize();
209     }
210 
211     @Override
212     public void setAsyncSendTimeout(long ms)
213     {
214         super.setAsyncSendTimeout(ms);
215         webSocketServerFactory.getPolicy().setAsyncWriteTimeout(ms);
216     }
217 
218     @Override
219     public void setDefaultMaxBinaryMessageBufferSize(int max)
220     {
221         super.setDefaultMaxBinaryMessageBufferSize(max);
222         // overall message limit (used in non-streaming)
223         webSocketServerFactory.getPolicy().setMaxBinaryMessageSize(max);
224         // incoming streaming buffer size
225         webSocketServerFactory.getPolicy().setMaxBinaryMessageBufferSize(max);
226     }
227 
228     @Override
229     public void setDefaultMaxSessionIdleTimeout(long ms)
230     {
231         super.setDefaultMaxSessionIdleTimeout(ms);
232         webSocketServerFactory.getPolicy().setIdleTimeout(ms);
233     }
234 
235     @Override
236     public void setDefaultMaxTextMessageBufferSize(int max)
237     {
238         super.setDefaultMaxTextMessageBufferSize(max);
239         // overall message limit (used in non-streaming)
240         webSocketServerFactory.getPolicy().setMaxTextMessageSize(max);
241         // incoming streaming buffer size
242         webSocketServerFactory.getPolicy().setMaxTextMessageBufferSize(max);
243     }
244 
245     @Override
246     public void onSessionClosed(WebSocketSession session)
247     {
248         webSocketServerFactory.onSessionClosed(session);
249     }
250 
251     @Override
252     public void onSessionOpened(WebSocketSession session)
253     {
254         webSocketServerFactory.onSessionOpened(session);
255     }
256 }