package org.argeo.cms.jcr.acr; import java.security.PrivilegedAction; import java.util.Collections; import java.util.HashMap; import java.util.Map; import javax.jcr.Repository; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.security.auth.Subject; import org.apache.jackrabbit.core.SessionImpl; import org.argeo.api.acr.spi.ProvidedSession; import org.argeo.jcr.JcrException; import org.argeo.jcr.JcrUtils; /** Manages JCR {@link Session} in an ACR context. */ class JcrSessionAdapter { private Repository repository; private Subject subject; private ProvidedSession contentSession; private Map> threadSessions = Collections.synchronizedMap(new HashMap<>()); private boolean closed = false; private Thread lastRetrievingThread = null; public JcrSessionAdapter(Repository repository, ProvidedSession contentSession, Subject subject) { this.repository = repository; this.contentSession = contentSession; this.subject = subject; } public synchronized void close() { for (Map sessions : threadSessions.values()) { for (Session session : sessions.values()) { JcrUtils.logoutQuietly(session); } sessions.clear(); } threadSessions.clear(); closed = true; } public synchronized Session getSession(String workspace) { if (closed) throw new IllegalStateException("JCR session adapter is closed."); Thread currentThread = Thread.currentThread(); if (lastRetrievingThread == null) lastRetrievingThread = currentThread; Map threadSession = threadSessions.get(currentThread); if (threadSession == null) { threadSession = new HashMap<>(); threadSessions.put(currentThread, threadSession); } Session session = threadSession.get(workspace); if (session == null) { session = Subject.doAs(subject, (PrivilegedAction) () -> { try { // String username = CurrentUser.getUsername(subject); // SimpleCredentials credentials = new SimpleCredentials(username, new char[0]); // credentials.setAttribute(ProvidedSession.class.getName(), contentSession); Session sess = repository.login(workspace); // Jackrabbit specific: ((SessionImpl)sess).setAttribute(ProvidedSession.class.getName(), contentSession); return sess; } catch (RepositoryException e) { throw new IllegalStateException("Cannot log in to " + workspace, e); } }); threadSession.put(workspace, session); } if (lastRetrievingThread != currentThread) { try { session.refresh(true); } catch (RepositoryException e) { throw new JcrException("Cannot refresh JCR session " + session, e); } } lastRetrievingThread = currentThread; return session; } }