Package org.springmodules.jcr

Source Code of org.springmodules.jcr.SessionFactoryUtils$JcrSessionSynchronization

package org.springmodules.jcr;

import java.io.IOException;

import javax.jcr.AccessDeniedException;
import javax.jcr.InvalidItemStateException;
import javax.jcr.InvalidSerializedDataException;
import javax.jcr.ItemExistsException;
import javax.jcr.ItemNotFoundException;
import javax.jcr.LoginException;
import javax.jcr.MergeException;
import javax.jcr.NamespaceException;
import javax.jcr.NoSuchWorkspaceException;
import javax.jcr.PathNotFoundException;
import javax.jcr.ReferentialIntegrityException;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.UnsupportedRepositoryOperationException;
import javax.jcr.ValueFormatException;
import javax.jcr.lock.LockException;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NoSuchNodeTypeException;
import javax.jcr.query.InvalidQueryException;
import javax.jcr.version.VersionException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;

/**
* FactoryBean for instantiating a Java Content Repository. This abstract class adds
* custom functionality subclasses handling only the configuration issues.
*
*
* @author Costin Leau
*
*/
public abstract class SessionFactoryUtils {

  private static final Log logger = LogFactory.getLog(SessionFactoryUtils.class);

  /**
   * Get a JCR Session for the given Repository. Is aware of and will return
   * any existing corresponding Session bound to the current thread, for
   * example when using JcrTransactionManager. Same as <code>getSession</code>
   * but throws the original Repository.
   *
   * @param sessionFactory Jcr Repository to create session with
   * @param allowCreate
   *            if a non-transactional Session should be created when no
   *            transactional Session can be found for the current thread
   *
   * @throws RepositoryException
   * @return
   */
  public static Session doGetSession(SessionFactory sessionFactory, boolean allowCreate)
      throws RepositoryException {
    Assert.notNull(sessionFactory, "No sessionFactory specified");

    // check if there is any transaction going on
    SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
    if (sessionHolder != null && sessionHolder.getSession() != null)
      return sessionHolder.getSession();

    if (!allowCreate && !TransactionSynchronizationManager.isSynchronizationActive()) {
      throw new IllegalStateException("No session bound to thread, "
          + "and configuration does not allow creation of non-transactional one here");
    }

    logger.debug("Opening JCR Session");
    Session session = sessionFactory.getSession();

    if (TransactionSynchronizationManager.isSynchronizationActive()) {
      logger.debug("Registering transaction synchronization for JCR session");
      // Use same session for further JCR actions within the transaction
      // thread object will get removed by synchronization at transaction
      // completion.
      sessionHolder = sessionFactory.getSessionHolder(session);
      sessionHolder.setSynchronizedWithTransaction(true);
      TransactionSynchronizationManager.registerSynchronization(new JcrSessionSynchronization(
          sessionHolder, sessionFactory));
      TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder);
    }

    return session;
  }

  /**
   * Get a JCR Session for the given Repository. Is aware of and will return
   * any existing corresponding Session bound to the current thread, for
   * example when using JcrTransactionManager. Will create a new Session
   * otherwise, if allowCreate is true. This is the getSession method used by
   * typical data access code, in combination with releaseSession called when
   * done with the Session. Note that JcrTemplate allows to write data access
   * code without caring about such resource handling. Supports
   * synchronization with both Spring-managed JTA transactions (i.e.
   * JtaTransactionManager) and non-Spring JTA transactions (i.e. plain JTA or
   * EJB CMT).
   *
   * @param sessionFactory JCR Repository to create session with
   * @param allowCreate
   *            if a non-transactional Session should be created when no
   *            transactional Session can be found for the current thread
   *
   * @throws DataAccessException        
   * @return
   */
  public static Session getSession(SessionFactory sessionFactory, boolean allowCreate)
      throws DataAccessException {
    try {
      return doGetSession(sessionFactory, allowCreate);
    }
    catch (RepositoryException ex) {
      throw new DataAccessResourceFailureException("Could not open Jcr Session", ex);
    }
  }

  /**
   * Return whether the given JCR Session is thread-bound that is, bound to
   * the current thread by Spring's transaction facilities (which is used as a thread-bounding
   * utility class).
   *
   * @param session
   *            the JCR Session to check
   * @param sessionFactory
   *            the JCR SessionFactory that the Session was created with (can
   *            be null)
   * @return whether the Session is transactional
   */
  public static boolean isSessionThreadBound(Session session, SessionFactory sessionFactory) {
    if (sessionFactory == null) {
      return false;
    }
    SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
    return (sessionHolder != null && session == sessionHolder.getSession());
  }

  /**
   * Close the given Session, created via the given repository, if it is not
   * managed externally (i.e. not bound to the thread).
   *
   * @param session
   *            the Jcr Session to close
   * @param sessionFactory
   *            JcrSessionFactory that the Session was created with (can be
   *            null)
   */
  public static void releaseSession(Session session, SessionFactory sessionFactory) {
    if (session == null) {
      return;
    }
    // Only close non thread bound Sessions.
    if (!isSessionThreadBound(session, sessionFactory)) {
      logger.debug("Closing JCR Session");
      session.logout();
    }
  }

  /**
   * Jcr exception translator - it converts specific JSR-170 checked exceptions into
   * unchecked Spring DA exception.
   *
   * @author Guillaume Bort <guillaume.bort@zenexity.fr>
   * @author Costin Leau
   *
   * @param ex
   * @return
   */
  public static DataAccessException translateException(RepositoryException ex) {
    if (ex instanceof AccessDeniedException) {
      return new DataRetrievalFailureException("Access denied to this data", ex);
    }
    if (ex instanceof ConstraintViolationException) {
      return new DataIntegrityViolationException("Constraint has been violated", ex);
    }
    if (ex instanceof InvalidItemStateException) {
      return new ConcurrencyFailureException("Invalid item state", ex);
    }
    if (ex instanceof InvalidQueryException) {
      return new DataRetrievalFailureException("Invalid query", ex);
    }
    if (ex instanceof InvalidSerializedDataException) {
      return new DataRetrievalFailureException("Invalid serialized data", ex);
    }
    if (ex instanceof ItemExistsException) {
      return new DataIntegrityViolationException("An item already exists", ex);
    }
    if (ex instanceof ItemNotFoundException) {
      return new DataRetrievalFailureException("Item not found", ex);
    }
    if (ex instanceof LoginException) {
      return new DataAccessResourceFailureException("Bad login", ex);
    }
    if (ex instanceof LockException) {
      return new ConcurrencyFailureException("Item is locked", ex);
    }
    if (ex instanceof MergeException) {
      return new DataIntegrityViolationException("Merge failed", ex);
    }
    if (ex instanceof NamespaceException) {
      return new InvalidDataAccessApiUsageException("Namespace not registred", ex);
    }
    if (ex instanceof NoSuchNodeTypeException) {
      return new InvalidDataAccessApiUsageException("No such node type", ex);
    }
    if (ex instanceof NoSuchWorkspaceException) {
      return new DataAccessResourceFailureException("Workspace not found", ex);
    }
    if (ex instanceof PathNotFoundException) {
      return new DataRetrievalFailureException("Path not found", ex);
    }
    if (ex instanceof ReferentialIntegrityException) {
      return new DataIntegrityViolationException("Referential integrity violated", ex);
    }
    if (ex instanceof UnsupportedRepositoryOperationException) {
      return new InvalidDataAccessApiUsageException("Unsupported operation", ex);
    }
    if (ex instanceof ValueFormatException) {
      return new InvalidDataAccessApiUsageException("Incorrect value format", ex);
    }
    if (ex instanceof VersionException) {
      return new DataIntegrityViolationException("Invalid version graph operation", ex);
    }
    // fallback
    return new JcrSystemException(ex);
  }

  /**
   * Jcr exception translator - it converts specific JSR-170 checked exceptions into
   * unchecked Spring DA exception.
   *
   * @param ex
   * @return
   */
  public static DataAccessException translateException(IOException ex) {
    return new DataAccessResourceFailureException("I/O failure", ex);
  }

  /**
   * Callback for resource cleanup at the end of a non-JCR transaction (e.g.
   * when participating in a JtaTransactionManager transaction).
   *
   * @see org.springframework.transaction.jta.JtaTransactionManager
   */
  private static class JcrSessionSynchronization extends TransactionSynchronizationAdapter {

    private final SessionHolder sessionHolder;

    private final SessionFactory sessionFactory;

    private boolean holderActive = true;

    /**
     * @param sessionFactory
     * @param holder
     */
    public JcrSessionSynchronization(SessionHolder holder, SessionFactory sessionFactory) {
      this.sessionFactory = sessionFactory;
      sessionHolder = holder;
    }

    public void suspend() {
      if (this.holderActive) {
        TransactionSynchronizationManager.unbindResource(this.sessionFactory);
      }
    }

    public void resume() {
      if (this.holderActive) {
        TransactionSynchronizationManager.bindResource(this.sessionFactory, this.sessionHolder);
      }
    }

    public void beforeCompletion() {
      TransactionSynchronizationManager.unbindResource(this.sessionFactory);
      this.holderActive = false;
      releaseSession(this.sessionHolder.getSession(), this.sessionFactory);
    }
  }

}
TOP

Related Classes of org.springmodules.jcr.SessionFactoryUtils$JcrSessionSynchronization

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.