1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.web.socket;
18
19 import java.io.IOException;
20 import javax.servlet.DispatcherType;
21 import javax.servlet.Filter;
22 import javax.servlet.Servlet;
23 import javax.servlet.ServletException;
24
25 import io.undertow.Undertow;
26 import io.undertow.server.HttpHandler;
27 import io.undertow.servlet.api.DeploymentInfo;
28 import io.undertow.servlet.api.DeploymentManager;
29 import io.undertow.servlet.api.FilterInfo;
30 import io.undertow.servlet.api.InstanceFactory;
31 import io.undertow.servlet.api.InstanceHandle;
32 import io.undertow.websockets.jsr.WebSocketDeploymentInfo;
33 import org.xnio.ByteBufferSlicePool;
34 import org.xnio.OptionMap;
35 import org.xnio.Xnio;
36
37 import org.springframework.util.Assert;
38 import org.springframework.util.SocketUtils;
39 import org.springframework.web.context.WebApplicationContext;
40 import org.springframework.web.servlet.DispatcherServlet;
41
42 import static io.undertow.servlet.Servlets.*;
43
44
45
46
47
48
49 public class UndertowTestServer implements WebSocketTestServer {
50
51 private int port = -1;
52
53 private Undertow server;
54
55 private DeploymentManager manager;
56
57
58 @Override
59 public void setup() {
60 this.port = SocketUtils.findAvailableTcpPort();
61 }
62
63 @Override
64 public int getPort() {
65 return this.port;
66 }
67
68 @Override
69 public void deployConfig(WebApplicationContext cxt, Filter... filters) {
70 Assert.state(this.port != -1, "setup() was never called");
71 DispatcherServletInstanceFactory servletFactory = new DispatcherServletInstanceFactory(cxt);
72
73
74 WebSocketDeploymentInfo info = new WebSocketDeploymentInfo();
75 try {
76 info.setWorker(Xnio.getInstance().createWorker(OptionMap.EMPTY));
77 info.setBuffers(new ByteBufferSlicePool(1024,1024));
78 }
79 catch (IOException ex) {
80 throw new IllegalStateException(ex);
81 }
82
83 DeploymentInfo servletBuilder = deployment()
84 .setClassLoader(UndertowTestServer.class.getClassLoader())
85 .setDeploymentName("undertow-websocket-test")
86 .setContextPath("/")
87 .addServlet(servlet("DispatcherServlet", DispatcherServlet.class, servletFactory).addMapping("/").setAsyncSupported(true))
88 .addServletContextAttribute(WebSocketDeploymentInfo.ATTRIBUTE_NAME, info);
89 for (final Filter filter : filters) {
90 String filterName = filter.getClass().getName();
91 servletBuilder.addFilter(new FilterInfo(filterName, filter.getClass(), new FilterInstanceFactory(filter)).setAsyncSupported(true));
92 for (DispatcherType type : DispatcherType.values()) {
93 servletBuilder.addFilterUrlMapping(filterName, "/*", type);
94 }
95 }
96 try {
97 this.manager = defaultContainer().addDeployment(servletBuilder);
98 this.manager.deploy();
99 HttpHandler httpHandler = this.manager.start();
100 this.server = Undertow.builder().addHttpListener(this.port, "localhost").setHandler(httpHandler).build();
101 }
102 catch (ServletException ex) {
103 throw new IllegalStateException(ex);
104 }
105 }
106
107 @Override
108 public void undeployConfig() {
109 this.manager.undeploy();
110 }
111
112 @Override
113 public void start() throws Exception {
114 this.server.start();
115 }
116
117 @Override
118 public void stop() throws Exception {
119 this.server.stop();
120 }
121
122
123 private static class DispatcherServletInstanceFactory implements InstanceFactory<Servlet> {
124
125 private final WebApplicationContext wac;
126
127 public DispatcherServletInstanceFactory(WebApplicationContext wac) {
128 this.wac = wac;
129 }
130
131 @Override
132 public InstanceHandle<Servlet> createInstance() throws InstantiationException {
133 return new InstanceHandle<Servlet>() {
134 @Override
135 public Servlet getInstance() {
136 return new DispatcherServlet(wac);
137 }
138 @Override
139 public void release() {
140 }
141 };
142 }
143 }
144
145 private static class FilterInstanceFactory implements InstanceFactory<Filter> {
146
147 private final Filter filter;
148
149 private FilterInstanceFactory(Filter filter) {
150 this.filter = filter;
151 }
152
153 @Override
154 public InstanceHandle<Filter> createInstance() throws InstantiationException {
155 return new InstanceHandle<Filter>() {
156 @Override
157 public Filter getInstance() {
158 return filter;
159 }
160 @Override
161 public void release() {}
162 };
163 }
164 }
165
166 }