/**
* The MIT License
* Copyright (c) 2010 Tad Glines
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.glines.socketio.server;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.util.IO;
import com.glines.socketio.server.transport.FlashSocketTransport;
import com.glines.socketio.server.transport.HTMLFileTransport;
import com.glines.socketio.server.transport.JSONPPollingTransport;
import com.glines.socketio.server.transport.WebSocketTransport;
import com.glines.socketio.server.transport.XHRMultipartTransport;
import com.glines.socketio.server.transport.XHRPollingTransport;
/**
*/
public abstract class SocketIOServlet extends HttpServlet {
public static final String BUFFER_SIZE_INIT_PARAM = "bufferSize";
public static final String MAX_IDLE_TIME_INIT_PARAM = "maxIdleTime";
public static final int BUFFER_SIZE_DEFAULT = 8192;
public static final int MAX_IDLE_TIME_DEFAULT = 300*1000;
private static final long serialVersionUID = 1L;
private SocketIOSessionManager sessionManager = null;
private Map<String, Transport> transports = new HashMap<String, Transport>();
@Override
public void init() throws ServletException {
super.init();
String str = this.getInitParameter(BUFFER_SIZE_INIT_PARAM);
int bufferSize = str==null ? BUFFER_SIZE_DEFAULT : Integer.parseInt(str);
str = this.getInitParameter(MAX_IDLE_TIME_INIT_PARAM);
int maxIdleTime = str==null ? MAX_IDLE_TIME_DEFAULT : Integer.parseInt(str);
sessionManager = new SocketIOSessionManager();
WebSocketTransport websocketTransport = new WebSocketTransport(bufferSize, maxIdleTime);
FlashSocketTransport flashsocketTransport = new FlashSocketTransport(bufferSize, maxIdleTime);
HTMLFileTransport htmlFileTransport = new HTMLFileTransport(bufferSize, maxIdleTime);
XHRMultipartTransport xhrMultipartTransport = new XHRMultipartTransport(bufferSize, maxIdleTime);
XHRPollingTransport xhrPollingTransport = new XHRPollingTransport(bufferSize, maxIdleTime);
JSONPPollingTransport jsonpPollingTransport = new JSONPPollingTransport(bufferSize, maxIdleTime);
transports.put(websocketTransport.getName(), websocketTransport);
transports.put(flashsocketTransport.getName(), flashsocketTransport);
transports.put(htmlFileTransport.getName(), htmlFileTransport);
transports.put(xhrMultipartTransport.getName(), xhrMultipartTransport);
transports.put(xhrPollingTransport.getName(), xhrPollingTransport);
transports.put(jsonpPollingTransport.getName(), jsonpPollingTransport);
for (Transport t: transports.values()) {
t.init(this.getServletConfig());
}
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
serve(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
serve(req, resp);
}
private void serve(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String path = request.getPathInfo();
if (path == null || path.length() == 0 || "/".equals(path)) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Missing SocketIO transport");
return;
}
if (path.startsWith("/")) path = path.substring(1);
String[] parts = path.split("/");
Transport transport = transports.get(parts[0]);
if (transport == null) {
if ("GET".equals(request.getMethod()) && "socket.io.js".equals(parts[0])) {
response.setContentType("text/javascript");
InputStream is = this.getClass().getClassLoader().getResourceAsStream("com/glines/socketio/socket.io.js");
OutputStream os = response.getOutputStream();
IO.copy(is, os);
return;
} else {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Unknown SocketIO transport");
return;
}
}
transport.handle(request, response, new Transport.InboundFactory() {
@Override
public SocketIOInbound getInbound(HttpServletRequest request) {
return SocketIOServlet.this.doSocketIOConnect(request);
}
}, sessionManager);
}
@Override
public void destroy() {
for (Transport t: transports.values()) {
t.destroy();
}
super.destroy();
}
/**
* Returns an instance of SocketIOInbound or null if the connection is to be denied.
* The value of cookies and protocols may be null.
*/
protected abstract SocketIOInbound doSocketIOConnect(HttpServletRequest request);
}