Open Source Repository

Home /hibernate/hibernate-3.2.7.ga | Repository Home


org/hibernate/context/ManagedSessionContext.java
package org.hibernate.context;

import org.hibernate.classic.Session;
import org.hibernate.HibernateException;
import org.hibernate.SessionFactory;
import org.hibernate.engine.SessionFactoryImplementor;

import java.util.Map;
import java.util.HashMap;

/**
 * Represents a {@link CurrentSessionContext} the notion of a contextual session
 * is managed by some external entity (generally some form of interceptor, etc).
 * This external manager is responsible for scoping these contextual sessions
 * appropriately binding/unbinding them here for exposure to the application
 * through {@link SessionFactory#getCurrentSession} calls.
 <p/>
 *  Basically exposes two interfaces.  <ul>
 <li>First is the implementation of CurrentSessionContext which is then used
 * by the {@link SessionFactory#getCurrentSession()} calls.  This
 * portion is instance-based specific to the session factory owning the given
 * instance of this impl (there will be one instance of this per each session
 * factory using this strategy).
 <li>Second is the externally facing methods {@link #hasBind}{@link #bind},
 * and {@link #unbind} used by the external thing to manage exposure of the
 * current session it is scoping.  This portion is static to allow easy
 * reference from that external thing.
 </ul>
 * The underlying storage of the current sessions here is a static
 {@link ThreadLocal}-based map where the sessions are keyed by the
 * the owning session factory.
 *
 @author Steve Ebersole
 */
public class ManagedSessionContext implements CurrentSessionContext {

  private static final ThreadLocal context = new ThreadLocal();
  private final SessionFactoryImplementor factory;

  public ManagedSessionContext(SessionFactoryImplementor factory) {
    this.factory = factory;
  }

  /**
   @see CurrentSessionContext#currentSession
   */
  public Session currentSession() {
    Session current = existingSessionfactory );
    if current == null ) {
      throw new HibernateException"No session currently bound to execution context" );
    }
    return current;
  }

  /**
   * Check to see if there is already a session associated with the current
   * thread for the given session factory.
   *
   @param factory The factory against which to check for a given session
   * within the current thread.
   @return True if there is currently a session bound.
   */
  public static boolean hasBind(SessionFactory factory) {
    return existingSessionfactory != null;
  }

  /**
   * Binds the given session to the current context for its session factory.
   *
   @param session The session to be bound.
   @return Any previously bound session (should be null in most cases).
   */
  public static Session bind(Session session) {
    return Session sessionMaptrue ).putsession.getSessionFactory(), session );
  }

  /**
   * Unbinds the session (if one) current associated with the context for the
   * given session.
   *
   @param factory The factory for which to unbind the current session.
   @return The bound session if one, else null.
   */
  public static Session unbind(SessionFactory factory) {
    Session existing = null;
    Map sessionMap = sessionMap();
    if sessionMap != null ) {
      existing = Session sessionMap.removefactory );
      doCleanup();
    }
    return existing;
  }

  private static Session existingSession(SessionFactory factory) {
    Map sessionMap = sessionMap();
    if sessionMap == null ) {
      return null;
    }
    else {
      return Session sessionMap.getfactory );
    }
  }

  protected static Map sessionMap() {
    return sessionMapfalse );
  }

  private static synchronized Map sessionMap(boolean createMap) {
    Map sessionMap = Map context.get();
    if sessionMap == null && createMap ) {
      sessionMap = new HashMap();
      context.setsessionMap );
    }
    return sessionMap;
  }

  private static synchronized void doCleanup() {
    Map sessionMap = sessionMapfalse );
    if sessionMap != null ) {
      if sessionMap.isEmpty() ) {
        context.setnull );
      }
    }
  }
}