package com.googlecode.tawus.hibernate.internal.services;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.tapestry5.ioc.services.ClassNameLocator;
import org.apache.tapestry5.ioc.services.RegistryShutdownListener;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import com.googlecode.tawus.hibernate.services.SessionFactoryConfiguration;
import com.googlecode.tawus.hibernate.services.SessionFactorySource;
/**
* Session Factory Source Implementation.
*/
public class SessionFactorySourceImpl implements SessionFactorySource,
RegistryShutdownListener {
private final Map<String, SessionFactory> factoryMap = new HashMap<String, SessionFactory>();
private final Map<Class<?>, String> entityMap = new HashMap<Class<?>, String>();
private final ClassNameLocator classNameLocator;
/**
* Constructor
*
* @param configurations
* database configurations
*/
public SessionFactorySourceImpl(final ClassNameLocator classNameLocator,
final List<SessionFactoryConfiguration> configurations) {
this.classNameLocator = classNameLocator;
for(final SessionFactoryConfiguration configuration : configurations){
setupDB(configuration);
}
}
private void setupDB(SessionFactoryConfiguration configuration) {
setupSessionFactory(configuration);
}
private void setupSessionFactory(
final SessionFactoryConfiguration configuration) {
final Configuration hibernateConfig = new Configuration();
final List<Class<?>> entities = loadEntityClasses(configuration);
// Load entity classes
for(final Class<?> entityClass : entities){
hibernateConfig.addAnnotatedClass(entityClass);
entityMap.put(entityClass, configuration.getFactoryId());
}
configuration.configure(hibernateConfig);
final SessionFactory sf = hibernateConfig.buildSessionFactory();
if(configuration.getFactoryId() != null){
factoryMap.put(configuration.getFactoryId(), sf);
}
}
private List<Class<?>> loadEntityClasses(
final SessionFactoryConfiguration configuration) {
final ClassLoader classLoader = Thread.currentThread()
.getContextClassLoader();
final List<Class<?>> entityClasses = new ArrayList<Class<?>>();
for(final String packageName : configuration.getPackageNames()){
for(final String className : classNameLocator
.locateClassNames(packageName)){
try{
Class<?> entityClass = null;
entityClass = classLoader.loadClass(className);
if(entityClass.getAnnotation(javax.persistence.Entity.class) != null ||
entityClass.getAnnotation(javax.persistence.MappedSuperclass.class) != null){
entityClasses.add(entityClass);
}
}catch(ClassNotFoundException e){
throw new RuntimeException(e);
}
}
}
return entityClasses;
}
public boolean hasSessionFactory(final Class<?> entityClass){
String factoryId = entityMap.get(entityClass);
if(factoryId == null){
return false;
}
return hasSessionFactory(factoryId);
}
public boolean hasSessionFactory(final String factoryId){
return factoryMap.get(factoryId) != null;
}
public SessionFactory getSessionFactory(final String factoryId) {
SessionFactory sf = factoryMap.get(factoryId);
if(sf == null){
throw new RuntimeException("No session factory found for factoryId: "
+ factoryId);
}
return sf;
}
public SessionFactory getSessionFactory(final Class<?> entityClass) {
SessionFactory sf = getSessionFactory(entityMap.get(entityClass));
if(sf == null){
throw new RuntimeException("No session factory found for entity: "
+ entityClass);
}
return sf;
}
public void registryDidShutdown() {
for(final SessionFactory sessionFactory : factoryMap.values()){
sessionFactory.close();
}
}
public Session createSession(Class<?> entityClass) {
return createSession(getFactoryId(entityClass));
}
public Session createSession(String factoryId) {
final Session session = getSessionFactory(factoryId).openSession();
return session;
}
public String getFactoryId(Class<?> entityClass) {
return entityMap.get(entityClass);
}
}