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());
       }
     }
   }
 }

Reply via email to