package com.mysema.luja.impl; import java.util.HashMap; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.mysema.commons.lang.Assert; import com.mysema.luja.LuceneSession; import com.mysema.luja.LuceneSessionFactory; import com.mysema.query.QueryException; /** * Holds the thread local sessions. This can handle several session factories * per thread. * * @author laim */ public final class LuceneSessionHolder { private static final Logger logger = LoggerFactory.getLogger(LuceneSessionHolder.class); private static final ThreadLocal<Map<LuceneSessionFactory, LuceneSession>> sessions = new ThreadLocal<Map<LuceneSessionFactory, LuceneSession>>(); private static final ThreadLocal<TransactionalScope> scope = new ThreadLocal<TransactionalScope>(); private static class TransactionalScope { private final boolean readOnly; private TransactionalScope(boolean readOnly) { this.readOnly = readOnly; } } private LuceneSessionHolder() { } public static boolean isTransactionalScope() { return scope.get() != null; } public static boolean hasCurrentSession(LuceneSessionFactory sessionFactory) { return getSessions().get(sessionFactory) != null; } public static LuceneSession getCurrentSession(LuceneSessionFactory sessionFactory) { return getSessions().get(sessionFactory); } public static void setCurrentSession(LuceneSessionFactory sessionFactory, LuceneSession session) { if (getSessions().containsKey(sessionFactory)) { throw new IllegalStateException( "Session factory has already bound a session to thread : " + sessionFactory); } getSessions().put(sessionFactory, session); } private static Map<LuceneSessionFactory, LuceneSession> getSessions() { if (sessions.get() == null) { sessions.set(new HashMap<LuceneSessionFactory, LuceneSession>()); } return sessions.get(); } public static void release() { release(false); } private static void release(boolean rollback) { if (scope.get() == null) { throw new QueryException( "There is no transactional scope to release"); } try { for (LuceneSession session : getSessions().values()) { try { if (rollback) { session.rollback(); } else { // System.out.println("session holder close"); session.close(); } } catch (QueryException e) { // System.out.println("failed to close session " + // e.getCause().getMessage()); logger.error("Failed to close session", e); } } } finally { sessions.remove(); scope.remove(); } } public static void lease(boolean readOnly) { if (isTransactionalScope()) { throw new QueryException("There is already a transactional scope"); } scope.set(new TransactionalScope(readOnly)); } public static boolean getReadOnly() { Assert.notNull(scope.get(), "No transactional scope"); return scope.get().readOnly; } public static void rollbackAndRelease() { release(true); } }