Hi, sorry the delay - sure I can share what I have done. And please send any
comments freely, if you can see any issues in the way I made it - I'm not
filter expert, for example mutex may be used too widely etc..
Thanks for the code.
If no session exists when the filter is first used, it doesn't store a
SEMAPHORE_REQUEST_IN_PROGRESS etc. in the session. This means that the
first request could create and use a session without any synchronisation.
I.e.:
(1) First request creates and starts using a session.
(2) Meanwhile, a second request comes in, and, since there is no
SEMAPHORE_REQUEST_IN_PROGRESS in the session, is processed immediately.
(3) Both requests can access the session, resulting in a possible race.
(I suppose it would also be better to remove the two session attributes at
the end of the filter, as this would use a bit less memory.)
Jeremy
private static final Object mutex = new Object();
public void doMainProcessing(ServletRequest request, ServletResponse
response, FilterChain chain) {
HttpServletRequest httpReq = (HttpServletRequest) request;
HttpServletResponse httpResp = (HttpServletResponse) response;
String uri = httpReq.getRequestURI();
HttpSession mySession = ((HttpServletRequest)
request).getSession(false);
synchronized (mutex) {
Boolean requestInProgess = null;
if (mySession != null) {
requestInProgess = (Boolean) mySession
.getAttribute("SEMAPHORE_REQUEST_IN_PROGRESS");
if (requestInProgess != null) {
if (requestInProgess.booleanValue()) {
String userAgent = httpReq.getHeader
("User-Agent").toLowerCase();
/* IE */
if (null != userAgent && userAgent.indexOf("msie") > -1) {
httpResp.setStatus(HttpServletResponse.SC_NO_CONTENT);
} else {
/* Other browsers */
httpResp.setHeader("Refresh","3; URL="+ mySession.getAttribute
("SEMAPHORE_REQUEST_URI"));
}
return;
}
}
mySession.setAttribute("SEMAPHORE_REQUEST_IN_PROGRESS", Boolean.TRUE
);
mySession.setAttribute("SEMAPHORE_REQUEST_URI", uri);
}
}
try {
chain.doFilter(request, httpResp);
} catch (Exception ex) {
throw new RuntimeException(ex);
} finally {
synchronized (mutex) {
try {
HttpSession afterSession = ((HttpServletRequest)
request).getSession(false);
if (afterSession != null) {
afterSession.setAttribute("SEMAPHORE_REQUEST_IN_PROGRESS",
Boolean.FALSE);
}
} catch (Exception ex) {
logger .fine("Session already terminated in DoubleClickFilter : "+
ex.getMessage());
}
}
}
}