View Javadoc
1   /*
2    * Copyright 2002-2014 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.web.socket.adapter.standard;
18  
19  import java.io.IOException;
20  import java.net.InetSocketAddress;
21  import java.net.URI;
22  import java.security.Principal;
23  import java.util.ArrayList;
24  import java.util.List;
25  import java.util.Map;
26  import javax.websocket.CloseReason;
27  import javax.websocket.CloseReason.CloseCodes;
28  import javax.websocket.Extension;
29  import javax.websocket.Session;
30  
31  import org.springframework.http.HttpHeaders;
32  import org.springframework.web.socket.BinaryMessage;
33  import org.springframework.web.socket.CloseStatus;
34  import org.springframework.web.socket.PingMessage;
35  import org.springframework.web.socket.PongMessage;
36  import org.springframework.web.socket.TextMessage;
37  import org.springframework.web.socket.WebSocketExtension;
38  import org.springframework.web.socket.WebSocketSession;
39  import org.springframework.web.socket.adapter.AbstractWebSocketSession;
40  
41  /**
42   * A {@link WebSocketSession} for use with the standard WebSocket for Java API.
43   *
44   * @author Rossen Stoyanchev
45   * @since 4.0
46   */
47  public class StandardWebSocketSession extends AbstractWebSocketSession<Session> {
48  
49  	private String id;
50  
51  	private URI uri;
52  
53  	private final HttpHeaders handshakeHeaders;
54  
55  	private String acceptedProtocol;
56  
57  	private List<WebSocketExtension> extensions;
58  
59  	private Principal user;
60  
61  	private final InetSocketAddress localAddress;
62  
63  	private final InetSocketAddress remoteAddress;
64  
65  
66  	/**
67  	 * Class constructor.
68  	 *
69  	 * @param headers the headers of the handshake request
70  	 * @param attributes attributes from the HTTP handshake to associate with the WebSocket
71  	 * session; the provided attributes are copied, the original map is not used.
72  	 * @param localAddress the address on which the request was received
73  	 * @param remoteAddress the address of the remote client
74  	 */
75  	public StandardWebSocketSession(HttpHeaders headers, Map<String, Object> attributes,
76  			InetSocketAddress localAddress, InetSocketAddress remoteAddress) {
77  
78  		this(headers, attributes, localAddress, remoteAddress, null);
79  	}
80  
81  	/**
82  	 * Class constructor that associates a user with the WebSocket session.
83  	 *
84  	 * @param headers the headers of the handshake request
85  	 * @param attributes attributes from the HTTP handshake to associate with the WebSocket session
86  	 * @param localAddress the address on which the request was received
87  	 * @param remoteAddress the address of the remote client
88  	 * @param user the user associated with the session; if {@code null} we'll
89  	 * 	fallback on the user available in the underlying WebSocket session
90  	 */
91  	public StandardWebSocketSession(HttpHeaders headers, Map<String, Object> attributes,
92  			InetSocketAddress localAddress, InetSocketAddress remoteAddress, Principal user) {
93  
94  		super(attributes);
95  		headers = (headers != null) ? headers : new HttpHeaders();
96  		this.handshakeHeaders = HttpHeaders.readOnlyHttpHeaders(headers);
97  		this.user = user;
98  		this.localAddress = localAddress;
99  		this.remoteAddress = remoteAddress;
100 	}
101 
102 
103 	@Override
104 	public String getId() {
105 		checkNativeSessionInitialized();
106 		return this.id;
107 	}
108 
109 	@Override
110 	public URI getUri() {
111 		checkNativeSessionInitialized();
112 		return this.uri;
113 	}
114 
115 	@Override
116 	public HttpHeaders getHandshakeHeaders() {
117 		return this.handshakeHeaders;
118 	}
119 
120 	@Override
121 	public String getAcceptedProtocol() {
122 		checkNativeSessionInitialized();
123 		return this.acceptedProtocol;
124 	}
125 
126 	@Override
127 	public List<WebSocketExtension> getExtensions() {
128 		checkNativeSessionInitialized();
129 		return this.extensions;
130 	}
131 
132 	public Principal getPrincipal() {
133 		return this.user;
134 	}
135 
136 	@Override
137 	public InetSocketAddress getLocalAddress() {
138 		return this.localAddress;
139 	}
140 
141 	@Override
142 	public InetSocketAddress getRemoteAddress() {
143 		return this.remoteAddress;
144 	}
145 
146 	@Override
147 	public void setTextMessageSizeLimit(int messageSizeLimit) {
148 		checkNativeSessionInitialized();
149 		getNativeSession().setMaxTextMessageBufferSize(messageSizeLimit);
150 	}
151 
152 	@Override
153 	public int getTextMessageSizeLimit() {
154 		checkNativeSessionInitialized();
155 		return getNativeSession().getMaxTextMessageBufferSize();
156 	}
157 
158 	@Override
159 	public void setBinaryMessageSizeLimit(int messageSizeLimit) {
160 		checkNativeSessionInitialized();
161 		getNativeSession().setMaxBinaryMessageBufferSize(messageSizeLimit);
162 	}
163 
164 	@Override
165 	public int getBinaryMessageSizeLimit() {
166 		checkNativeSessionInitialized();
167 		return getNativeSession().getMaxBinaryMessageBufferSize();
168 	}
169 
170 	@Override
171 	public boolean isOpen() {
172 		return (getNativeSession() != null && getNativeSession().isOpen());
173 	}
174 
175 	@Override
176 	public void initializeNativeSession(Session session) {
177 		super.initializeNativeSession(session);
178 
179 		this.id = session.getId();
180 		this.uri = session.getRequestURI();
181 
182 		this.acceptedProtocol = session.getNegotiatedSubprotocol();
183 
184 		List<Extension> source = getNativeSession().getNegotiatedExtensions();
185 		this.extensions = new ArrayList<WebSocketExtension>(source.size());
186 		for (Extension ext : source) {
187 			this.extensions.add(new StandardToWebSocketExtensionAdapter(ext));
188 		}
189 
190 		if (this.user == null) {
191 			this.user = session.getUserPrincipal();
192 		}
193 	}
194 
195 	@Override
196 	protected void sendTextMessage(TextMessage message) throws IOException {
197 		getNativeSession().getBasicRemote().sendText(message.getPayload(), message.isLast());
198 	}
199 
200 	@Override
201 	protected void sendBinaryMessage(BinaryMessage message) throws IOException {
202 		getNativeSession().getBasicRemote().sendBinary(message.getPayload(), message.isLast());
203 	}
204 
205 	@Override
206 	protected void sendPingMessage(PingMessage message) throws IOException {
207 		getNativeSession().getBasicRemote().sendPing(message.getPayload());
208 	}
209 
210 	@Override
211 	protected void sendPongMessage(PongMessage message) throws IOException {
212 		getNativeSession().getBasicRemote().sendPong(message.getPayload());
213 	}
214 
215 	@Override
216 	protected void closeInternal(CloseStatus status) throws IOException {
217 		getNativeSession().close(new CloseReason(CloseCodes.getCloseCode(status.getCode()), status.getReason()));
218 	}
219 
220 }