class SessionValidator {

    private volatile long wrongPasswordDelay = SysProperties.DELAY_WRONG_PASSWORD_MIN;
    private long lastTime;
    private long delay;

    /**
     * This method is called after validating user name and password. If user
     * name and password were correct, the sleep time is reset, otherwise this
     * method waits some time (to make brute force / rainbow table attacks
     * harder) and then throws a 'wrong user or password' exception. The delay
     * is a bit randomized to protect against timing attacks. Also the delay
     * doubles after each unsuccessful logins, to make brute force attacks
     * harder.
     *
     * There is only one exception message both for wrong user and for
     * wrong password, to make it harder to get the list of user names. This
     * method must only be called from one place, so it is not possible from the
     * stack trace to see if the user name was wrong or the password.
     *
     * @param isUserAndPasswordCorrect if the user name or the password was correct
     * @throws DbException the exception 'wrong user or password'
     */
    public void validate(boolean isUserAndPasswordCorrect) {<FILL_FUNCTION_BODY>}

    public boolean canHandleNextSessionInitTask() {
        if (delay > 0) {
            if (lastTime + delay > System.currentTimeMillis())
                return false;
            delay = 0;
        }
        return true;
    }
}

        int min = SysProperties.DELAY_WRONG_PASSWORD_MIN;
        if (isUserAndPasswordCorrect) {
            long delay = wrongPasswordDelay;
            if (delay > min && delay > 0) {
                // delay up to the last delay
                // an attacker can't know how long it will be
                this.delay = MathUtils.secureRandomInt((int) delay);
                wrongPasswordDelay = min;
                lastTime = System.currentTimeMillis();
            }
        } else {
            this.delay = wrongPasswordDelay;
            int max = SysProperties.DELAY_WRONG_PASSWORD_MAX;
            if (max <= 0) {
                max = Integer.MAX_VALUE;
            }
            wrongPasswordDelay += wrongPasswordDelay;
            if (wrongPasswordDelay > max || wrongPasswordDelay < 0) {
                wrongPasswordDelay = max;
            }
            if (min > 0) {
                // a bit more to protect against timing attacks
                this.delay += Math.abs(MathUtils.secureRandomLong() % 100);
            }
            lastTime = System.currentTimeMillis();
        }
    
<no_super_class>