org.wings.comet.CometConnectionManager Maven / Gradle / Ivy
package org.wings.comet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wings.plaf.css.Utils;
/**
* Manages open HangingGet requests and limits their number per browser.
*
* This is necessary to circumvent browsers connection limits. The number of
* concurrent connections per host is limited as follows (see https://bugzilla.mozilla.org/show_bug.cgi?id=423377):
*
* - Firefox 2: 2
* - Firefox 3: 6
* - Opera 9.26: 4
* - Opera 9.5 beta: 4
* - Safari 3.0.4 Mac/Windows: 4
* - IE 7: 2
* - IE 8: 6
*
* If this maximum number of connections would be all occupied by HangingGet
* requests, all network traffic of this browser would be blocked. To avoid this
* the number of HangingGet requests should be limited to a number below the
* maximum number of connections.
*
* Subclasses implement different strategies to restrict the number of
* HangingGet requests.
*/
public abstract class CometConnectionManager {
static final String COOKIE_NAME = "COMET_BROWSER";
static final String NAME = "org.wings.comet.connectionSet";
private String browserId = null;
private int maxHangingGetCount;
protected static final transient Logger log = LoggerFactory.getLogger(CometConnectionManager.class);
protected CometConnectionManager() {
maxHangingGetCount = determineMaxHangingGetCount();
}
/**
* Checks whether another HangingGet request could be opened by the current
* browser (i.e. the maximum number of HangingGet requests isn't yet reached
* for this browser)
*/
abstract boolean canAddHangingGet();
/**
* Adds an incoming HangingGet request to the number of managed HangingGets.
* This is possible only if the maximum number of HangingGets isn't yet
* reached for this browser.
*
* @return true, if the HangingGet request was successfully added. Returns
* false, if the limit is reached. In this case the HangingGet
* request should be rejected
*/
abstract boolean addHangingGet();
/**
* Removes one HangingGet request from the number of managed HangingGets.
*/
abstract void removeHangingGet();
public void setBrowserId(HttpServletRequest request, HttpServletResponse response) {
String browser_id = getBrowserIdFromCookie(request);
if (browser_id == null) {
browser_id = setupCometBrowserCookie(request, response);
log.debug("setupCometBrowserCookie: browser_id="+browser_id);
}
this.browserId = browser_id;
log.debug("setBrowserId: browser_id="+browser_id);
}
protected String getBrowserId(){
return browserId;
}
protected int getMaxHangingGetCount(){
return maxHangingGetCount;
}
private static String getBrowserIdFromCookie(HttpServletRequest request) {
final Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (COOKIE_NAME.equals(cookie.getName())) {
return cookie.getValue();
}
}
}
return null;
}
private static String setupCometBrowserCookie(HttpServletRequest request, HttpServletResponse response) {
final String browser_id = Long.toHexString(System.currentTimeMillis()) +
Long.toHexString(request.getRemoteAddr().hashCode());
final Cookie cookie = new Cookie(COOKIE_NAME, browser_id);
cookie.setPath("/");
cookie.setMaxAge(-1);
response.addCookie(cookie);
return browser_id;
}
private static int determineMaxHangingGetCount() {
if (Utils.isMSIE(8))
return 4;
if (Utils.isGECKO(3))
return 4;
// TODO: Increase and Test for other Browsers
return 1;
}
}