package com.peterphi.std.guice.hibernate.module;

import com.google.inject.Inject;
import com.google.inject.Provider;
import com.peterphi.std.guice.common.shutdown.iface.ShutdownManager;
import com.peterphi.std.guice.common.shutdown.iface.StoppableService;
import org.apache.log4j.Logger;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

/**
 * A SessionFactory Provider for Guice
 */
class HibernateSessionFactoryProvider implements Provider<SessionFactory>, StoppableService
{
	private static final Logger log = Logger.getLogger(HibernateSessionFactoryProvider.class);

	private final Provider<ServiceRegistry> serviceRegistryProvider;
	private final Configuration config;

	private SessionFactory sessionFactory;


	@Inject
	public HibernateSessionFactoryProvider(ShutdownManager coordinator,
	                                       Provider<ServiceRegistry> serviceRegistryProvider,
	                                       Configuration config)
	{
		this.serviceRegistryProvider = serviceRegistryProvider;
		this.config = config;

		coordinator.register(this);
	}


	public synchronized SessionFactory get()
	{
		if (this.sessionFactory == null)
		{
			final ServiceRegistry serviceRegistry = serviceRegistryProvider.get();

			this.sessionFactory = config.buildSessionFactory(serviceRegistry);
			log.trace("Hibernate Setup Complete.");
		}

		return sessionFactory;
	}


	@Override
	public void shutdown()
	{
		log.info("Shut down Hibernate SessionFactory...");

		if (sessionFactory != null)
		{
			sessionFactory.close();
			sessionFactory = null;
		}
	}
}

@@ -250,16 +250,125 @@
 ervice;%0A
+import com.peterphi.std.guice.database.annotation.Transactional;%0Aimport org.apache.commons.lang.StringUtils;%0A
 import o
@@ -387,24 +387,24 @@
 g4j.Logger;%0A
-
 import org.h
@@ -515,16 +515,44 @@
 istry;%0A%0A
+import javax.inject.Named;%0A%0A
 /**%0A * A
@@ -922,16 +922,301 @@
 ctory;%0A%0A
+%09@Inject(optional = true)%0A%09@Named(HIBERNATE_SHUTDOWN_SQL)%0A%09private String shutdownSql;%0A%0A%09/*%0A%09%09A service/environment property that contains some sql to be run on the database before a shutdown occurs.%0A%09 */%0A%09public static final String HIBERNATE_SHUTDOWN_SQL = %22hibernate.shutdown.sql%22;%0A%0A
 %0A%09@Injec
@@ -1993,16 +1993,37 @@
 ll)%0A%09%09%7B%0A
+%09%09%09runShutDownSQL();%0A
 %09%09%09sessi
@@ -2037,24 +2037,24 @@
 ry.close();%0A
-
 %09%09%09sessionFa
@@ -2071,13 +2071,253 @@
 ll;%0A%09%09%7D%0A
+%09%09else%0A%09%09%7B%0A%09%09%09log.info(%22SessionFactory already null%22);%0A%09%09%7D%0A%09%7D%0A%0A%0A%09@Transactional%0A%09void runShutDownSQL()%0A%09%7B%0A%09%09if (StringUtils.isNotEmpty(shutdownSql))%0A%09%09%7B%0A%09%09%09sessionFactory.getCurrentSession().createSQLQuery(shutdownSql).executeUpdate();%0A%09%09%7D%0A
 %09%7D%0A%7D%0A

Allow configuration to specify a query to be run when hibernate environment is shutting down. This is useful for hsqldb which requires a SHUTDOWN command to be sent if the database is to shutdown without the jvm stopping (otherwise a lock file remains)