Project: logback-audit
/**
 * Logback: the reliable, generic, fast and flexible logging framework. 
 * Copyright (C) 2006-2011, QOS.ch. All rights reserved. 
 *  
 * This program and the accompanying materials are dual-licensed under 
 * either the terms of the Eclipse Public License v1.0 as published by 
 * the Eclipse Foundation 
 *   
 *   or (per the licensee's choosing) 
 *   
 * under the terms of the GNU Lesser General Public License version 2.1 
 * as published by the Free Software Foundation. 
 */
 
package ch.qos.logback.audit.persistent; 
 
import org.hibernate.HibernateException; 
import org.hibernate.Session; 
import org.hibernate.SessionFactory; 
import org.hibernate.Transaction; 
import org.hibernate.cfg.Configuration; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
 
import ch.qos.logback.audit.AuditEvent; 
 
/**
 * Base functionality "class" for all Persistor classes - this class only 
 * bundles static functions, has no members nor methods. 
 *  
 * Persistor includes functions to create or retrieve a Hibernate 
 * SessionFactory, and functions to open, close or rollback sessions. 
 *  
 * @author Ceki Glc? 
 */
 
public class Persistor { 
 
  // static Logger staticLogger = LoggerFactory.getLogger(Persistor.class); 
  static SessionFactory sessionFactory; 
  static Configuration cfg; 
  static Object cfgLock; 
  static Logger logger = LoggerFactory.getLogger(Persistor.class); 
 
  /**
   * Create or re-obtain our single Hibernate SessionFactory. 
   *  
   * @return An instantiated SessionFactory, always the same (the created 
   *         instance is cached in this class). 
   * @throws HibernateException 
   */
 
  private static SessionFactory getSessionFactory() throws HibernateException { 
    if (sessionFactory == null) { 
      // Double-locked synchronization pattern 
      synchronized (SessionFactory.class) { 
        if (sessionFactory == null) { 
          sessionFactory = createSessionFactory(); 
        } 
      } 
    } 
    return sessionFactory; 
  } 
 
  static public Configuration createConfiguration() { 
    final Configuration cfg = new Configuration(); 
 
    // Configure Hibernate mappings,this will look for the "hbm.xml" resources. 
    // In alphabetical order: 
    cfg.addClass(AuditEvent.class); 
 
    return cfg; 
  } 
 
  public static void setConfiguration(Configuration cfg, Object lock) { 
    // set the lock if not set previously 
    if (Persistor.cfgLock == null && lock != null) { 
      Persistor.cfgLock = lock; 
    } 
    if (Persistor.cfgLock == null || Persistor.cfgLock.equals(lock)) { 
      Persistor.cfg = cfg; 
    } else if (Persistor.cfg == null) { 
      Persistor.cfg = cfg; 
    } else { 
      throw new IllegalStateException("Configuration was already set."); 
    } 
  } 
 
  public static void resetConfiguration(Object lock) { 
    if (Persistor.cfgLock == null || Persistor.cfgLock.equals(lock)) { 
      Persistor.cfg = null
      if (Persistor.sessionFactory != null) { 
        try { 
          Persistor.sessionFactory.close(); 
        } catch (HibernateException he) { 
          logger.error("Warn failed to close session factory", he); 
        } 
      } 
      Persistor.sessionFactory = null
 
    } 
  } 
 
  static SessionFactory createSessionFactory() { 
    if (cfg == null) { 
      throw new IllegalStateException("Configuration must be set before usage."); 
    } 
    return cfg.buildSessionFactory(); 
  } 
 
  /**
   * Open an Hibernate Session. 
   *  
   * @return A valid Session instance, never null. 
   * @throws HibernateException 
   *                         In case the session could not be created. 
   */
 
  protected static Session openSession() throws HibernateException { 
    final SessionFactory sessionFactory = getSessionFactory(); 
    return sessionFactory.openSession(); 
  } 
 
  protected static void update(Object o) throws HibernateException { 
    Session s = null
    Transaction tx = null
    try { 
      s = openSession(); 
      tx = s.beginTransaction(); 
      s.update(o); 
      tx.commit(); 
    } catch (HibernateException he) { 
      if (tx != null) { 
        tx.rollback(); 
      } 
      throw he; 
    } finally { 
      close(s, tx); 
    } 
  } 
 
  public static void save(Object o) throws HibernateException { 
    Session s = null
    Transaction tx = null
    try { 
      s = openSession(); 
      tx = s.beginTransaction(); 
      s.save(o); 
      tx.commit(); 
    } catch (HibernateException he) { 
      logger.error("Failed to save object", he); 
      if (tx != null) { 
        tx.rollback(); 
      } 
      throw he; 
    } finally { 
      close(s, tx); 
    } 
  } 
 
  static private Logger getStaticLogger() { 
    return LoggerFactory.getLogger(Persistor.class); 
  } 
 
  public static void delete(Object o) throws HibernateException { 
    Session s = null
    Transaction tx = null
    try { 
      s = openSession(); 
      tx = s.beginTransaction(); 
      s.delete(o); 
      tx.commit(); 
    } catch (HibernateException he) { 
      if (tx != null) { 
        tx.rollback(); 
      } 
      throw he; 
    } finally { 
      close(s, tx); 
    } 
  } 
 
  /**
   * Close a Hibernate Session. 
   *  
   * @param theHibernateSession 
   *                        The open session to close. 
   *  
   * In case of a problem, this method will log an error but won't propagate any 
   * exception - therefore it may be used safely in a finally{} block. 
   *  
   */
 
  protected static void close(Session theHibernateSession) { 
    try { 
      if (theHibernateSession != null) { 
        theHibernateSession.close(); 
      } 
    } catch (Exception e) { 
      getStaticLogger().error("Failed to close session " + theHibernateSession, 
          e); 
    } 
  } 
 
  /**
   * Rollback a Hibernate transaction and close the session. 
   *  
   * In case of a problem, this method will log an error but won't propagate any 
   * exception - therefore it may be used safely in a finally{} block. 
   *  
   * @param theHibernateSession 
   *                        The open session to rollback and close. 
   * @param tx 
   */
 
  protected static void close(Session theHibernateSession, Transaction tx) { 
    try { 
      if ((tx != null) && (tx.isActive() && !tx.wasCommitted())) { 
        tx.rollback(); 
      } 
    } catch (HibernateException he) { 
      getStaticLogger().error("Could not rollback transaction" + tx); 
    } 
 
    try { 
      if (theHibernateSession != null) { 
        theHibernateSession.close(); 
      } 
    } catch (Exception e) { 
      getStaticLogger().error("Failed to close session " + theHibernateSession, 
          e); 
    } 
  } 
}