/** * 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 G�lc� */ 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); } } }