CRXSessionCache.java 13 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.day.crx.CRXSession
 *  javax.jcr.Credentials
 *  javax.jcr.LoginException
 *  javax.jcr.Repository
 *  javax.jcr.RepositoryException
 *  javax.jcr.Session
 *  javax.jcr.SimpleCredentials
 *  javax.jcr.Workspace
 *  javax.servlet.ServletException
 *  javax.servlet.http.HttpServletRequest
 *  javax.servlet.http.HttpServletResponse
 *  javax.servlet.http.HttpSession
 *  javax.servlet.http.HttpSessionBindingEvent
 *  javax.servlet.http.HttpSessionBindingListener
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.day.crx.explorer.impl.j2ee;

import com.day.crx.CRXSession;
import com.day.crx.explorer.impl.j2ee.CRXContext;
import com.day.crx.explorer.impl.j2ee.CRXCredentialsProvider;
import com.day.crx.explorer.impl.j2ee.JCRExplorerServlet;
import com.day.crx.explorer.impl.j2ee.LoginServlet;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.jcr.Credentials;
import javax.jcr.LoginException;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.jcr.Workspace;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CRXSessionCache {
    private static final Logger log = LoggerFactory.getLogger(CRXSessionCache.class);
    private static Logger logLogin = LoggerFactory.getLogger((String)(JCRExplorerServlet.class.getName() + ".login"));
    private final Map<CRXSessionId, Session> repSessions = new HashMap<CRXSessionId, Session>();
    private final JCRExplorerServlet repoServlet;
    private int sessionCounter;
    private Integer sessionTimeout;
    private ReadWriteLock lock = new ReentrantReadWriteLock();

    protected CRXSessionCache(JCRExplorerServlet repoServlet) {
        this.repoServlet = repoServlet;
    }

    protected void setSessionTimeout(Integer sessionTimeout) {
        this.sessionTimeout = sessionTimeout;
        log.info("CRX Session timeout set to {} seconds.", (Object)sessionTimeout);
    }

    public Session getDefaultSession(HttpServletRequest req) {
        HttpSession httpSession = req.getSession(true);
        CRXSessionId sessionId = this.getSessionId(httpSession);
        Session repSession = this.getValidCachedSession(req, sessionId);
        if (repSession == null) {
            try {
                return this.login(req, null, LoginServlet.getWorkspaceFromCookies(req));
            }
            catch (RepositoryException e) {
                log.warn("Unable to retrieve session: " + e.toString());
            }
        }
        return repSession;
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    public Session getSession(HttpServletRequest req) {
        CRXSessionId sessionId;
        HttpSession httpSession = req.getSession(false);
        if (httpSession != null && (sessionId = this.getSessionId(httpSession)) != null) {
            this.lock.readLock().lock();
            try {
                Session session = this.repSessions.get(sessionId);
                return session;
            }
            finally {
                this.lock.readLock().unlock();
            }
        }
        return null;
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    public Session login(HttpServletRequest req, Credentials creds, String workspace) throws RepositoryException {
        Session repSession;
        block9 : {
            Repository repo;
            if (creds == null) {
                try {
                    creds = new CRXCredentialsProvider("guestcredentials").getCredentials(req);
                }
                catch (Exception e) {
                    creds = new SimpleCredentials("anonymous", "anonymous".toCharArray());
                }
            }
            if ((repo = this.repoServlet.getRepository()) == null) {
                throw new RepositoryException("Repository not available, yet.");
            }
            repSession = this.repoServlet.getRepository().login(creds, workspace);
            this.lock.writeLock().lock();
            try {
                CRXSessionId sessionId = this.getOrCreateSessionId(req);
                if (repSession != null) {
                    Session oldSession = this.repSessions.get(sessionId);
                    if (oldSession != null) {
                        logLogin.info("User '" + oldSession.getUserID() + "' logged out. sid=" + sessionId);
                        oldSession.logout();
                    }
                    this.repSessions.put(sessionId, repSession);
                    logLogin.info("User '" + repSession.getUserID() + "' logged in. ws=" + repSession.getWorkspace().getName() + ", sid=" + sessionId);
                    break block9;
                }
                this.repSessions.remove(sessionId);
            }
            finally {
                this.lock.writeLock().unlock();
            }
        }
        return repSession;
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    public Session login(CRXContext ctx, HttpServletResponse response) throws RepositoryException, ServletException {
        Session repSession;
        block5 : {
            repSession = LoginServlet.login(ctx, response);
            this.lock.writeLock().lock();
            try {
                CRXSessionId sessionId = this.getOrCreateSessionId(ctx.getRequest());
                if (repSession != null) {
                    Session oldSession = this.repSessions.get(sessionId);
                    if (oldSession != null) {
                        logLogin.info("User '" + oldSession.getUserID() + "' logged out. sid=" + sessionId);
                        oldSession.logout();
                    }
                    this.repSessions.put(sessionId, repSession);
                    logLogin.info("User '" + repSession.getUserID() + "' logged in. ws=" + repSession.getWorkspace().getName() + ", sid=" + sessionId);
                    break block5;
                }
                this.repSessions.remove(sessionId);
            }
            finally {
                this.lock.writeLock().unlock();
            }
        }
        return repSession;
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    private void logoutSession(CRXSessionId sessionId) {
        if (sessionId != null) {
            this.lock.writeLock().lock();
            try {
                Session s = this.repSessions.remove(sessionId);
                if (s != null && s.isLive()) {
                    String userid = s.getUserID();
                    s.logout();
                    logLogin.info("User '" + userid + "' logged out. sid=" + sessionId);
                }
            }
            finally {
                this.lock.writeLock().unlock();
            }
        }
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    public Session switchWorkspace(HttpServletRequest req, String workspace) throws RepositoryException {
        HttpSession httpSession = req.getSession(true);
        CRXSessionId sessionId = this.getSessionId(httpSession);
        if (sessionId == null) {
            throw new LoginException("Not logged in.");
        }
        this.lock.writeLock().lock();
        try {
            Session oldSession = this.repSessions.get(sessionId);
            if (!(oldSession instanceof CRXSession)) {
                throw new LoginException("Not logged in or no CRXSession.");
            }
            CRXSession repSession = ((CRXSession)oldSession).getSession(workspace);
            logLogin.info("User '" + oldSession.getUserID() + "' logged out. sid=" + sessionId);
            oldSession.logout();
            logLogin.info("User '" + repSession.getUserID() + "' logged in. ws=" + repSession.getWorkspace().getName() + ", sid=" + sessionId);
            this.repSessions.put(sessionId, (Session)repSession);
            CRXSession cRXSession = repSession;
            return cRXSession;
        }
        finally {
            this.lock.writeLock().unlock();
        }
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    public Session impersonate(HttpServletRequest req, String userId) throws RepositoryException {
        CRXSessionId sessionId = this.getOrCreateSessionId(req);
        this.lock.writeLock().lock();
        try {
            Session oldSession = this.repSessions.get(sessionId);
            if (oldSession == null) {
                throw new LoginException("Existing session needed to impersonate.");
            }
            Session repSession = oldSession.impersonate((Credentials)new SimpleCredentials(userId, new char[0]));
            oldSession.logout();
            logLogin.info("User '" + oldSession.getUserID() + "' impersonated to '" + repSession.getUserID() + "'. sid=" + sessionId);
            this.repSessions.put(sessionId, repSession);
            Session session = repSession;
            return session;
        }
        finally {
            this.lock.writeLock().unlock();
        }
    }

    protected CRXSessionId getSessionId(HttpServletRequest req) {
        HttpSession httpSession = req.getSession(false);
        if (httpSession == null) {
            return null;
        }
        CRXSessionId sessionId = this.getSessionId(httpSession);
        if (sessionId == null) {
            return null;
        }
        return sessionId;
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    private Session getValidCachedSession(HttpServletRequest req, CRXSessionId sessionId) {
        boolean isLive;
        Session repSession;
        if (sessionId == null) {
            return null;
        }
        this.lock.readLock().lock();
        try {
            repSession = this.repSessions.get(sessionId);
        }
        finally {
            this.lock.readLock().unlock();
        }
        if (!(repSession == null || (isLive = repSession.isLive()) && this.matches(repSession, req))) {
            this.lock.writeLock().lock();
            try {
                this.repSessions.remove(sessionId);
            }
            finally {
                this.lock.writeLock().unlock();
            }
            if (isLive) {
                logLogin.info("User '" + repSession.getUserID() + "' logged out. sid=" + sessionId);
                repSession.logout();
            }
            repSession = null;
        }
        return repSession;
    }

    private boolean matches(Session session, HttpServletRequest req) {
        return true;
    }

    private CRXSessionId getSessionId(HttpSession httpSession) {
        try {
            return (CRXSessionId)httpSession.getAttribute("CRX_SESSION_ID");
        }
        catch (ClassCastException e) {
            httpSession.removeAttribute("CRX_SESSION_ID");
            return null;
        }
    }

    private CRXSessionId getOrCreateSessionId(HttpServletRequest req) {
        HttpSession httpSession = req.getSession(true);
        CRXSessionId sessionId = this.getSessionId(httpSession);
        if (sessionId == null) {
            sessionId = new CRXSessionId("" + this.sessionCounter++ + "-" + UUID.randomUUID().toString());
            httpSession.setAttribute("CRX_SESSION_ID", (Object)sessionId);
            if (this.sessionTimeout != null) {
                httpSession.setMaxInactiveInterval(this.sessionTimeout.intValue());
            }
        }
        return sessionId;
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    protected void logoutAll() {
        this.lock.writeLock().lock();
        try {
            for (Session session : this.repSessions.values()) {
                if (session == null || !session.isLive()) continue;
                session.logout();
            }
            this.repSessions.clear();
        }
        finally {
            this.lock.writeLock().unlock();
        }
    }

    protected class CRXSessionId
    implements HttpSessionBindingListener {
        final String id;
        private int numRef;

        public CRXSessionId(String id) {
            this.numRef = 0;
            this.id = id;
        }

        public void valueBound(HttpSessionBindingEvent event) {
        }

        public void valueUnbound(HttpSessionBindingEvent event) {
            this.release();
        }

        public void acquire() {
            ++this.numRef;
        }

        public void release() {
            if (--this.numRef < 0) {
                CRXSessionCache.this.logoutSession(this);
            }
        }

        public String toString() {
            return this.id;
        }
    }

}