package org.jblooming.persistence.hibernate; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.mapping.PersistentClass; import org.jblooming.PlatformRuntimeException; import org.jblooming.logging.Sniffer; import org.jblooming.ontology.IdentifiableSupport; import org.jblooming.persistence.ThreadLocalPersistenceContextCarrier; import org.jblooming.persistence.PersistenceHome; import org.jblooming.persistence.exceptions.PersistenceException; import org.jblooming.system.SystemConstants; import org.jblooming.tracer.Tracer; import org.jblooming.utilities.JSP; import org.jblooming.waf.constants.Fields; import org.jblooming.waf.settings.ApplicationState; import org.jblooming.waf.settings.PersistenceConfiguration; import javax.naming.Context; import javax.naming.InitialContext; import javax.sql.DataSource; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Iterator; /** * @author Pietro Polsinelli ppolsinelli@open-lab.com */ public class PersistenceContext { public Session session; public PersistenceConfiguration persistenceConfiguration; public static ThreadLocal<ThreadLocalPersistenceContextCarrier> threadLocalPersistenceContextCarrier = new ThreadLocal<ThreadLocalPersistenceContextCarrier>() { protected ThreadLocalPersistenceContextCarrier initialValue() { return null; } }; public PersistenceContext() { this((Connection) null); } public PersistenceContext(Connection c) { this(null, c); } /** * this is not managed by the filter */ public PersistenceContext(String persistenceConfigurationName, Connection c) { if (JSP.ex(persistenceConfigurationName)) persistenceConfiguration = PersistenceConfiguration.persistenceConfigurations.get(persistenceConfigurationName); else persistenceConfiguration = PersistenceConfiguration.getFirstPersistenceConfiguration(); Sniffer interceptor = null; if (Fields.TRUE.equals(ApplicationState.getApplicationSetting(SystemConstants.AUDIT))) interceptor = new Sniffer(); Throwable t = null; try { if (c != null && interceptor != null) session = persistenceConfiguration.getSessionFactory().openSession(c, interceptor); else if (c != null) session = persistenceConfiguration.getSessionFactory().openSession(c); else if (interceptor != null) session = persistenceConfiguration.getSessionFactory().openSession(interceptor); else session = persistenceConfiguration.getSessionFactory().openSession(); session.beginTransaction(); } catch (Throwable e) { t = e; } if (session == null ) throw new PlatformRuntimeException("PersistenceContext: unable to create session. It's null."); else if ( t != null ) throw new PlatformRuntimeException(t); } public static Connection getNewConnection() throws ClassNotFoundException, SQLException { PersistenceConfiguration pcf = PersistenceConfiguration.getDefaultPersistenceConfiguration(); String datasource = pcf.dataSource; if(JSP.ex(datasource)) { Connection dataSourceConnection = null; try { Context ctx = new InitialContext(); if (ctx == null ) throw new PlatformRuntimeException("No javax.naming.Context: connection can not be established!"); DataSource ds = (DataSource)ctx.lookup(datasource); dataSourceConnection = ds.getConnection(); } catch (Throwable throwable) { throw new PlatformRuntimeException("A connection can not be established:: " +throwable); } return dataSourceConnection; } else { Class.forName(pcf.driver_class); return DriverManager.getConnection(pcf.driver_url, pcf.db_user_name, pcf.db_user_psw); } } private void close(boolean thereHasBeenAnException) throws PersistenceException { boolean exceptionInCommit = true; if (!thereHasBeenAnException) { try { if (session.getTransaction() != null) { session.getTransaction().commit(); exceptionInCommit = false; } } catch (Throwable throwable) { Tracer.platformLogger.error(throwable); } } if (thereHasBeenAnException || exceptionInCommit) { try { if (session.getTransaction() != null) { session.getTransaction().rollback(); } } catch (Throwable throwable) { Tracer.platformLogger.error(throwable); } } try { //as we are NOT using Hibernate managed context, in contrast with FrontControllerFilter, there is need after commit/rollbacdk to close session session.close(); } catch (Throwable throwable) { throw new PersistenceException(throwable); } finally { session=null; ThreadLocalPersistenceContextCarrier carrier = threadLocalPersistenceContextCarrier.get(); if (carrier!=null && this.equals(carrier.currentPC)){ threadLocalPersistenceContextCarrier.get().currentPC = null; threadLocalPersistenceContextCarrier.set(null); } } } public void checkPoint() { if (session.isOpen()) { Transaction currentTransaction = session.getTransaction(); if (session.isOpen() && currentTransaction != null && !currentTransaction.wasRolledBack()) { session.flush(); currentTransaction.commit(); session.beginTransaction(); } } } public void commitAndClose() throws PersistenceException { close(false); } public void rollbackAndClose() { try { close(true); } catch (PersistenceException e) { } } public static PersistenceContext getDefaultPersistenceContext() { return switchTo((String) null); } public static PersistenceContext switchToFirst() { return switchTo(PersistenceConfiguration.getFirstPersistenceConfiguration().name); } public static PersistenceContext switchTo(Class<? extends IdentifiableSupport> persistentClass) { PersistenceContext persistenceContext = get(persistentClass); threadLocalPersistenceContextCarrier.get().currentPC = persistenceContext; return persistenceContext; } public static PersistenceContext switchTo(String persistenceConfigurationName) { // set last used as current PersistenceContext pc = getByConfigurationName(persistenceConfigurationName); threadLocalPersistenceContextCarrier.get().currentPC = pc; return pc; } public static PersistenceContext get(Class<? extends IdentifiableSupport> persistentClass) { String conf = null; for (String confName : PersistenceConfiguration.persistenceConfigurations.keySet()) { PersistenceConfiguration pcf = PersistenceConfiguration.persistenceConfigurations.get(confName); if (pcf.getHibernateConfiguration().getClassMapping(persistentClass.getName()) != null) { conf = confName; break; } } return getByConfigurationName(conf); } public static PersistenceContext get(IdentifiableSupport persistentObj) { String className=PersistenceHome.deProxy(persistentObj.getClass().getName()); String conf = null; for (String confName : PersistenceConfiguration.persistenceConfigurations.keySet()) { PersistenceConfiguration pcf = PersistenceConfiguration.persistenceConfigurations.get(confName); if (pcf.getHibernateConfiguration().getClassMapping(className) != null) { conf = confName; break; } } return getByConfigurationName(conf); } public static PersistenceContext get(String className) { PersistenceContext pc; try { pc = PersistenceContext.get((Class<? extends IdentifiableSupport>) Class.forName(className)); } catch (ClassNotFoundException e) { String conf = null; for (String confName : PersistenceConfiguration.persistenceConfigurations.keySet()) { PersistenceConfiguration pcf = PersistenceConfiguration.persistenceConfigurations.get(confName); Iterator ite= pcf.getHibernateConfiguration().getClassMappings(); while (ite.hasNext()){ PersistentClass pcla= (PersistentClass) ite.next(); if (pcla.getNodeName().equals(className)){ conf=confName; break; } } } if (JSP.ex(conf)) return getByConfigurationName(conf); else throw new PlatformRuntimeException(e); } return pc; } private static PersistenceContext getByConfigurationName(String persistenceConfigurationName) { //there could be already a closed session on it ThreadLocalPersistenceContextCarrier localPersistenceContextCarrier = null; // exists ThreadLocal? if (threadLocalPersistenceContextCarrier.get() == null) { localPersistenceContextCarrier = new ThreadLocalPersistenceContextCarrier(); threadLocalPersistenceContextCarrier.set(localPersistenceContextCarrier); } localPersistenceContextCarrier = threadLocalPersistenceContextCarrier.get(); // guess the right persistenceConfiguration Name PersistenceConfiguration persistenceConfiguration; if (JSP.ex(persistenceConfigurationName)) persistenceConfiguration = PersistenceConfiguration.persistenceConfigurations.get(persistenceConfigurationName); else { // if there is a current in use sedimented on threadlocal, give that if (localPersistenceContextCarrier.currentPC != null) persistenceConfiguration = localPersistenceContextCarrier.currentPC.persistenceConfiguration; //no current sedimented on threadlocal, use the first, "main" one else persistenceConfiguration = PersistenceConfiguration.getFirstPersistenceConfiguration(); } // exist a PersistentContext for this conf ? PersistenceContext persistenceContext = localPersistenceContextCarrier.getPersistenceContext(persistenceConfiguration.name); if (persistenceContext == null) { persistenceContext = new PersistenceContext(persistenceConfigurationName, null); localPersistenceContextCarrier.putPersistenceContext(persistenceContext); } else { // check if sessions are still good if (persistenceContext.session != null && !(persistenceContext.session.isOpen())) { persistenceContext = new PersistenceContext(persistenceConfigurationName, null); localPersistenceContextCarrier.putPersistenceContext(persistenceContext); Tracer.platformLogger.error("Creating currupted new pc thlocid:"+localPersistenceContextCarrier.hashCode()+"\n"+Tracer.getCallTrace(true)); } } return persistenceContext; } }