/**
 * OWASP Enterprise Security API (ESAPI)
 * 
 * This file is part of the Open Web Application Security Project (OWASP)
 * Enterprise Security API (ESAPI) project. For details, please see
 * <a href="http://www.owasp.org/index.php/ESAPI">http://www.owasp.org/index.php/ESAPI</a>.
 *
 * Copyright (c) 2007 - The OWASP Foundation
 * 
 * The ESAPI is published by OWASP under the BSD license. You should read and accept the
 * LICENSE before you use, modify, and/or redistribute this software.
 * 
 * @author Jeff Williams <a href="http://www.aspectsecurity.com">Aspect Security</a>
 * @created 2007
 */
package org.owasp.esapi.filters;

import java.io.IOException;
import java.util.Date;
import java.util.Stack;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * A simple servlet filter that limits the request rate to a certain threshold of requests per second.
 * The default rate is 5 hits in 10 seconds. This can be overridden in the web.xml file by adding
 * parameters named "hits" and "period" with the desired values. When the rate is exceeded, a short
 * string is written to the response output stream and the chain method is not invoked. Otherwise,
 * processing proceeds as normal.
 */
public class RequestRateThrottleFilter implements Filter
{

    private int hits = 5;

    private int period = 10;

    private static final String HITS = "hits";

    private static final String PERIOD = "period";

    /**
     * Called by the web container to indicate to a filter that it is being
     * placed into service. The servlet container calls the init method exactly
     * once after instantiating the filter. The init method must complete
     * successfully before the filter is asked to do any filtering work.
     * 
     * @param filterConfig
     *            configuration object
     */
    public void init(FilterConfig filterConfig)
    {
        hits = Integer.parseInt(filterConfig.getInitParameter(HITS));
        period = Integer.parseInt(filterConfig.getInitParameter(PERIOD));
    }

    /**
     * Checks to see if the current session has exceeded the allowed number
     * of requests in the specified time period. If the threshold has been
     * exceeded, then a short error message is written to the output stream and
     * no further processing is done on the request. Otherwise the request is
     * processed as normal.
     * @param request 
     * @param response 
     * @param chain 
     * @throws IOException
     * @throws ServletException
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
    {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpSession session = httpRequest.getSession(true);
        
        synchronized( session.getId().intern() ) {
	        Stack times = (Stack) session.getAttribute("times");
	        if (times == null)
	        {
	            times = new Stack();
	            times.push(new Date(0));
	            session.setAttribute("times", times);
	        }
	        times.push(new Date());
	        if (times.size() >= hits)
	        {
	            times.removeElementAt(0);
	        }
	        Date newest = (Date) times.get(times.size() - 1);
	        Date oldest = (Date) times.get(0);
	        long elapsed = newest.getTime() - oldest.getTime();        
	        if (elapsed < period * 1000) // seconds
	        {
	            response.getWriter().println("Request rate too high");
	            return;
	        }
        }        
        chain.doFilter(request, response);
    }

    /**
     * Called by the web container to indicate to a filter that it is being
     * taken out of service. This method is only called once all threads within
     * the filter's doFilter method have exited or after a timeout period has
     * passed. After the web container calls this method, it will not call the
     * doFilter method again on this instance of the filter.
     */
    public void destroy()
    {
        // finalize
    }

}
@@ -659,76 +659,29 @@
 ort 
-java.io.IOException;%0D%0Aimport java.util.Date;%0D%0Aimport java.util.Stack
+org.owasp.esapi.ESAPI
 ;%0D%0A%0D
@@ -702,22 +702,17 @@
 servlet.
-Filter
+*
 ;%0D%0Aimpor
@@ -731,259 +731,149 @@
 let.
-FilterChain;%0D%0Aimport javax.servlet.FilterConfig;%0D%0Aimport javax.servlet.ServletException;%0D%0Aimport javax.servlet.ServletRequest;%0D%0Aimport javax.servlet.ServletResponse;%0D%0Aimport javax.servlet.http.HttpServletRequest;%0D%0Aimport javax.servlet.http.HttpSession
+http.HttpServletRequest;%0D%0Aimport javax.servlet.http.HttpSession;%0D%0Aimport java.io.IOException;%0D%0Aimport java.util.Date;%0D%0Aimport java.util.Stack
 ;%0D%0A%0D
@@ -3003,16 +3003,22 @@
    Stack
+%3CDate%3E
  times =
@@ -3022,27 +3022,40 @@
 s = 
-(Stack) s
+ESAPI.httpUtilities().getS
 ession
-.get
 Attr
@@ -3142,16 +3142,22 @@
 ew Stack
+%3CDate%3E
 ();%0D%0A%09  
@@ -3408,31 +3408,24 @@
 ate newest =
- (Date)
  times.get(t
@@ -3469,15 +3469,8 @@
 st =
- (Date)
  tim

move to beef code