package org.mobicents.slee.container.deployment.profile.jpa; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import javax.naming.InitialContext; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Query; import javax.slee.SLEEException; import javax.slee.profile.ProfileTableAlreadyExistsException; import javax.transaction.Transaction; import org.apache.log4j.Logger; import org.hibernate.cfg.Environment; import org.hibernate.ejb.HibernatePersistence; import org.jboss.jpa.deployment.PersistenceUnitInfoImpl; import org.jboss.metadata.jpa.spec.PersistenceUnitMetaData; import org.mobicents.slee.container.SleeContainer; import org.mobicents.slee.container.component.ProfileSpecificationComponent; import org.mobicents.slee.container.management.SleeProfileTableManager; import org.mobicents.slee.container.management.jmx.MobicentsManagement; /** * * JPAProfileTableFramework.java * * @author <a href="mailto:brainslog@gmail.com"> Alexandre Mendonca </a> */ public class JPAProfileTableFramework { private static Logger logger = Logger.getLogger(JPAProfileTableFramework.class); private EntityManagerFactory entityManagerFactory; private final SleeProfileTableManager sptm; private boolean isInitialized = false; private static Boolean isLoading = false; public JPAProfileTableFramework(SleeProfileTableManager sptm) { this.sptm = sptm; } private void createPersistenceUnit() { try { HibernatePersistence hp = new HibernatePersistence(); PersistenceUnitMetaData pumd = new PersistenceUnitMetaData(); pumd.setProvider("org.hibernate.ejb.HibernatePersistence"); pumd.setJtaDataSource("java:/DefaultDS"); pumd.setExcludeUnlistedClasses(false); boolean persistProfiles = MobicentsManagement.persistProfiles; Map pumdProps = new HashMap(); pumdProps.put(Environment.HBM2DDL_AUTO, persistProfiles ? "update" : "create-drop"); pumdProps.put(Environment.DIALECT, "org.hibernate.dialect.HSQLDialect"); pumd.setProperties(pumdProps); pumd.setName("mobicents-profile-persistence-pu"); Set classes = new HashSet<String>(); classes.add(JPAProfileTable.class.getName()); pumd.setClasses(classes); Properties properties = new Properties(); properties.setProperty(Environment.DATASOURCE, "java:/DefaultDS"); properties.setProperty(Environment.TRANSACTION_STRATEGY, "org.hibernate.ejb.transaction.JoinableCMTTransactionFactory"); properties.setProperty(Environment.CONNECTION_PROVIDER, "org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider"); properties.setProperty("hibernate.jndi.java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces"); properties.setProperty(Environment.CACHE_PROVIDER, "org.hibernate.cache.HashtableCacheProvider"); properties.setProperty(Environment.TRANSACTION_MANAGER_STRATEGY, "org.hibernate.transaction.JBossTransactionManagerLookup"); properties.setProperty("hibernate.jndi.java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory"); properties.setProperty(Environment.DIALECT, "org.hibernate.dialect.HSQLDialect"); // FIXME: Should be Environment.JACC_CONTEXTID but it's // hibernate.jacc_context_id vs hibernate.jacc.ctx.id. Bug? properties.setProperty("hibernate.jacc.ctx.id", "persistence.xml"); properties.setProperty(Environment.CACHE_REGION_PREFIX, "persistence.unit:unitName=#" + pumd.getName()); properties.setProperty(Environment.SESSION_FACTORY_NAME, "persistence.unit:unitName=#" + pumd.getName()); properties.setProperty(Environment.HBM2DDL_AUTO, persistProfiles ? "update" : "create-drop"); properties.setProperty(Environment.USE_REFLECTION_OPTIMIZER, "false"); properties.setProperty(Environment.BYTECODE_PROVIDER, "javassist"); properties.setProperty(Environment.STATEMENT_BATCH_SIZE, "0"); properties.setProperty(Environment.SHOW_SQL, "false"); properties.setProperty(Environment.FORMAT_SQL, "false"); PersistenceUnitInfoImpl pi = new PersistenceUnitInfoImpl(pumd, properties, Thread.currentThread().getContextClassLoader(), ClassLoader.getSystemResource("."), new ArrayList<URL>(), new InitialContext()); Transaction tx = null; try { tx = SleeContainer.lookupFromJndi().getTransactionManager().suspend(); entityManagerFactory = hp.createContainerEntityManagerFactory(pi, null); isInitialized = true; } catch (Exception e) { logger.error("Failure creating Persistence Unit for profile persistency.", e); } catch (Throwable t) { logger.error("Failure creating Persistence Unit for profile persistency.", t); } finally { if (tx != null) SleeContainer.lookupFromJndi().getTransactionManager().resume(tx); } } catch (Exception e) { logger.error("Failure creating Persistence Unit for profile persistency.", e); } } public void storeProfileTable(JPAProfileTable profileTable) { if(isLoading) { return; } if(logger.isDebugEnabled()) { logger.debug( "Storing into backend storage profile table " + profileTable ); } EntityManager em = null; try { em = entityManagerFactory.createEntityManager(); em.persist(profileTable); } finally { if(em != null) { em.close(); em = null; } } } public void removeProfileTable(String profileTableName) { if(logger.isDebugEnabled()) { logger.debug( "Removing from backend storage profile table" + profileTableName ); } EntityManager em = null; try { em = entityManagerFactory.createEntityManager(); Query q = em.createQuery("DELETE FROM " + JPAProfileTable.class.getName() + " x WHERE x.profileTableName = :profileTableName") .setParameter("profileTableName", profileTableName); q.executeUpdate(); } finally { if(em != null) { em.close(); em = null; } } } public void renameProfileTable(String oldProfileTableName, String newProfileTableName) { if(logger.isDebugEnabled()) { logger.debug("Renaming " + oldProfileTableName + " to " + newProfileTableName + " in backend storage."); } EntityManager em = null; try { em = entityManagerFactory.createEntityManager(); Query q = em.createQuery("UPDATE " + JPAProfileTable.class.getName() + " x SET x.profileTableName = :newProfileTableName WHERE x.profileTableName = :oldProfileTableName") .setParameter("newProfileTableName", newProfileTableName).setParameter("oldProfileTableName", oldProfileTableName); q.executeUpdate(); } finally { if(em != null) { em.close(); em = null; } } } public void loadProfileTables(ProfileSpecificationComponent component) throws SLEEException, ProfileTableAlreadyExistsException { if(logger.isDebugEnabled()) { logger.debug("Loading from backend storage profile tables for " + component.getProfileSpecificationID()); } EntityManager em = null; try { if(!isInitialized) { createPersistenceUnit(); } em = entityManagerFactory.createEntityManager(); Query q = em.createQuery("SELECT x FROM " + JPAProfileTable.class.getName() + " x WHERE x.profileSpecId = :profileSpecId") .setParameter("profileSpecId", component.getProfileSpecificationID().toString()); List<JPAProfileTable> tables = q.getResultList(); for(JPAProfileTable table : tables) { if(logger.isDebugEnabled()) { logger.debug("Table [" + table.getProfileTableName() + "] found in storage."); } synchronized (isLoading) { isLoading = true; sptm.addProfileTable(table.getProfileTableName(), component); isLoading = false; } } } finally { if(em != null) { em.close(); em = null; } } } }