package jp.troter.servlet.httpsession;

import jp.troter.servlet.httpsession.spi.SessionIdGenerator;
import jp.troter.servlet.httpsession.spi.SessionStateManager;
import jp.troter.servlet.httpsession.spi.SessionValidator;


public class UserHttpSessionHolder {

    protected UserHttpSessionHttpServletRequestWrapper request;

    protected SessionStateManager sessionStateManager;

    protected UserHttpSession session;

    protected boolean sessionInvalidate = false;

    protected SessionValidator sessionValidator;

    protected SessionIdGenerator sessionIdGenerator;

    protected int retryLimit = 10;

    public UserHttpSessionHolder(UserHttpSessionHttpServletRequestWrapper request, SessionStateManager sessionStateManager) {
        this.request = request;
        this.sessionStateManager = sessionStateManager;
    }

    public UserHttpSession getUserHttpSession() {
        return session;
    }

    public UserHttpSession getSession() {
        return getSession(true);
    }

    public UserHttpSession getSession(boolean create) {
        // session already exists.
        if (session != null) { return session; }

        // session not exists, and not create
        if (!create) { return null; }

        boolean needNewSession = false;
        String sessionId = request.getRequestedSessionId();
        if (sessionId == null || invalidate()) {
            needNewSession = true;
            sessionId = getSessionIdGenerator().generateSessionId(request);
        }

        session = createHttpSession(sessionId, needNewSession);
        sessionInvalidate = false;

        return session;
    }

    protected UserHttpSession createHttpSession(final String sessionId, final boolean needNewSession) {
        String currentSessionId = sessionId;
        boolean isNew = needNewSession;
        int retry = 0;
        while (true) {
            if (retry > retryLimit) {
                throw new RuntimeException("cannot create session.");
            }
            UserHttpSession session = new UserHttpSession(request, currentSessionId, sessionStateManager, isNew);

            boolean isConflictSessionId = isNew && getSessionValidator().isExistsMarker(session);
            if (! isConflictSessionId) {
                getSessionValidator().setupMarker(session, request);
                if (getSessionValidator().isValid(session, request)) {
                    // session is valid. return.
                    return session;
                }
            }

            session.invalidate();
            currentSessionId = getSessionIdGenerator().generateSessionId(request, retry);
            isNew = true;
            retry++;
        }
    }

    /**
     * invalidate holding session.
     */
    public void sessionInvalidate() {
        session = null;
        sessionInvalidate = true;
    }

    public boolean invalidate() {
        return sessionInvalidate;
    }

    protected SessionValidator getSessionValidator() {
        if (sessionValidator == null) {
            sessionValidator = SessionValidator.newInstance();
        }
        return sessionValidator;
    }

    protected SessionIdGenerator getSessionIdGenerator() {
        if (sessionIdGenerator == null) {
            sessionIdGenerator = SessionIdGenerator.newInstance();
        }
        return sessionIdGenerator;
    }
}

@@ -420,58 +420,8 @@
 n;%0A%0A
-    protected boolean sessionInvalidate = false;%0A%0A
     
@@ -461,24 +461,24 @@
 nValidator;%0A
+
 %0A    protect
@@ -1504,43 +1504,8 @@
 on);
-%0A        sessionInvalidate = false;
 %0A%0A  
@@ -2707,42 +2707,8 @@
 ll;%0A
-        sessionInvalidate = true;%0A
     
@@ -2766,26 +2766,24 @@
  session
-Invalidate
+ == null
 ;%0A    %7D%0A

remove unuse variable