package org.jboss.hibernate.jmx;
import org.jboss.system.ServiceMBeanSupport;
import org.jboss.hibernate.cache.DeployedTreeCacheProvider;
import org.jboss.logging.Logger;
import org.jboss.naming.Util;
import java.net.URL;
import java.io.File;
import java.util.Properties;
import javax.management.Notification;
import javax.management.ObjectName;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.hibernate.cfg.Environment;
import org.hibernate.cfg.Configuration;
import org.hibernate.transaction.JBossTransactionManagerLookup;
import org.hibernate.transaction.JTATransactionFactory;
import org.hibernate.SessionFactory;
import org.hibernate.Interceptor;
import org.hibernate.HibernateException;
public class Hibernate
extends ServiceMBeanSupport
implements HibernateMBean
{
private static final Logger log = Logger.getLogger( Hibernate.class );
public static final String SESSION_FACTORY_CREATE = "hibernate.sessionfactory.create";
public static final String SESSION_FACTORY_DESTROY = "hibernate.sessionfactory.destroy";
private String datasourceName;
private String dialect;
private String defaultSchema;
private String defaultCatalog;
private String maxFetchDepth;
private String jdbcBatchSize;
private String batchVersionedDataEnabled;
private String jdbcFetchSize;
private String jdbcScrollableResultSetEnabled;
private String getGeneratedKeysEnabled;
private String streamsForBinaryEnabled;
private String reflectionOptimizationEnabled;
private String hbm2ddlAuto;
private String querySubstitutions;
private String showSqlEnabled;
private String username;
private String password;
private String queryCacheEnabled;
private String cacheProviderClass;
private ObjectName deployedTreeCacheObjectName;
private String minimalPutsEnabled;
private String cacheRegionPrefix;
private String sessionFactoryInterceptor;
private URL harUrl;
private String sessionFactoryName;
private boolean dirty = false;
private SessionFactory sessionFactory;
public String getSessionFactoryName()
{
return sessionFactoryName;
}
public void setSessionFactoryName(String sessionFactoryName)
{
this.sessionFactoryName = sessionFactoryName;
dirty = true;
}
public URL getHarUrl()
{
return harUrl;
}
public void setHarUrl(URL harUrl)
{
this.harUrl = harUrl;
dirty = true;
}
public String getDatasourceName()
{
return datasourceName;
}
public void setDatasourceName(String datasourceName)
{
this.datasourceName = datasourceName;
dirty = true;
}
public String getDefaultSchema()
{
return defaultSchema;
}
public void setDefaultSchema(String defaultSchema)
{
this.defaultSchema = defaultSchema;
dirty = true;
}
public String getDefaultCatalog()
{
return defaultCatalog;
}
public void setDefaultCatalog(String defaultCatalog)
{
this.defaultCatalog = defaultCatalog;
}
public String getHbm2ddlAuto()
{
return hbm2ddlAuto;
}
public void setHbm2ddlAuto(String hbm2ddlAuto)
{
this.hbm2ddlAuto = hbm2ddlAuto;
dirty = true;
}
public String getDialect()
{
return dialect;
}
public void setDialect(String dialect)
{
this.dialect = dialect;
dirty = true;
}
public String getMaxFetchDepth()
{
return maxFetchDepth;
}
public void setMaxFetchDepth(String maxFetchDepth)
{
this.maxFetchDepth = maxFetchDepth;
dirty = true;
}
public String getJdbcBatchSize()
{
return jdbcBatchSize;
}
public void setJdbcBatchSize(String jdbcBatchSize)
{
this.jdbcBatchSize = jdbcBatchSize;
dirty = true;
}
public String getJdbcFetchSize()
{
return jdbcFetchSize;
}
public void setJdbcFetchSize(String jdbcFetchSize)
{
this.jdbcFetchSize = jdbcFetchSize;
dirty = true;
}
public String getJdbcScrollableResultSetEnabled()
{
return jdbcScrollableResultSetEnabled;
}
public void setJdbcScrollableResultSetEnabled(String jdbcScrollableResultSetEnabled)
{
this.jdbcScrollableResultSetEnabled = jdbcScrollableResultSetEnabled;
dirty = true;
}
public String getGetGeneratedKeysEnabled()
{
return getGeneratedKeysEnabled;
}
public void setGetGeneratedKeysEnabled(String getGeneratedKeysEnabled)
{
this.getGeneratedKeysEnabled = getGeneratedKeysEnabled;
dirty = true;
}
public String getQuerySubstitutions()
{
return querySubstitutions;
}
public void setQuerySubstitutions(String querySubstitutions)
{
this.querySubstitutions = querySubstitutions;
dirty = true;
}
public String getQueryCacheEnabled()
{
return queryCacheEnabled;
}
public void setQueryCacheEnabled(String queryCacheEnabled)
{
this.queryCacheEnabled = queryCacheEnabled;
dirty = true;
}
public String getCacheProviderClass()
{
return cacheProviderClass;
}
public void setCacheProviderClass(String cacheProviderClass)
{
this.cacheProviderClass = cacheProviderClass;
dirty = true;
}
public String getCacheRegionPrefix()
{
return cacheRegionPrefix;
}
public void setCacheRegionPrefix(String cacheRegionPrefix)
{
this.cacheRegionPrefix = cacheRegionPrefix;
dirty = true;
}
public String getMinimalPutsEnabled()
{
return minimalPutsEnabled;
}
public void setMinimalPutsEnabled(String minimalPutsEnabled)
{
this.minimalPutsEnabled = minimalPutsEnabled;
dirty = true;
}
public String getShowSqlEnabled()
{
return showSqlEnabled;
}
public void setShowSqlEnabled(String showSqlEnabled)
{
this.showSqlEnabled = showSqlEnabled;
dirty = true;
}
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
dirty = true;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
dirty = true;
}
public String getSessionFactoryInterceptor()
{
return sessionFactoryInterceptor;
}
public void setSessionFactoryInterceptor(String sessionFactoryInterceptor)
{
this.sessionFactoryInterceptor = sessionFactoryInterceptor;
dirty = true;
}
public ObjectName getDeployedTreeCacheObjectName()
{
return deployedTreeCacheObjectName;
}
public void setDeployedTreeCacheObjectName(ObjectName deployedTreeCacheObjectName)
{
this.deployedTreeCacheObjectName = deployedTreeCacheObjectName;
}
public String getBatchVersionedDataEnabled()
{
return batchVersionedDataEnabled;
}
public void setBatchVersionedDataEnabled(String batchVersionedDataEnabled)
{
this.batchVersionedDataEnabled = batchVersionedDataEnabled;
this.dirty = true;
}
public String getStreamsForBinaryEnabled()
{
return streamsForBinaryEnabled;
}
public void setStreamsForBinaryEnabled(String streamsForBinaryEnabled)
{
this.streamsForBinaryEnabled = streamsForBinaryEnabled;
this.dirty = true;
}
public String getReflectionOptimizationEnabled()
{
return reflectionOptimizationEnabled;
}
public void setReflectionOptimizationEnabled(String reflectionOptimizationEnabled)
{
this.reflectionOptimizationEnabled = reflectionOptimizationEnabled;
this.dirty = true;
}
public boolean isDirty()
{
return dirty;
}
public boolean isSessionFactoryRunning()
{
return sessionFactory != null;
}
public void rebuildSessionFactory() throws Exception
{
destroySessionFactory();
buildSessionFactory();
}
public void startService() throws Exception
{
log.debug( "Hibernate MBean starting; " + this );
buildSessionFactory();
}
public void stopService() throws Exception
{
destroySessionFactory();
}
private void buildSessionFactory() throws Exception
{
log.debug( "Building SessionFactory; " + this );
Configuration cfg = new Configuration();
cfg.addProperties( getProperties() );
final File file = new File(harUrl.getFile());
if ( file.isDirectory() )
{
cfg.addDirectory( file );
}
else
{
cfg.addJar( file );
}
Interceptor interceptorInstance = generateInterceptorInstance();
if ( interceptorInstance != null )
{
cfg.setInterceptor( interceptorInstance );
}
sessionFactory = cfg.buildSessionFactory();
try {
bind();
}
catch( HibernateException e ) {
forceCleanup();
throw e;
}
dirty = false;
sendNotification(
new Notification(SESSION_FACTORY_CREATE, getServiceName(), getNextNotificationSequenceNumber())
);
log.info("SessionFactory successfully built and bound into JNDI [" + sessionFactoryName + "]");
}
private void destroySessionFactory() throws Exception
{
if (sessionFactory != null)
{
unbind();
sessionFactory.close();
sessionFactory = null;
sendNotification(
new Notification(SESSION_FACTORY_DESTROY, getServiceName(), getNextNotificationSequenceNumber())
);
}
}
private Properties getProperties()
{
Properties props = new Properties();
setUnlessNull(props, Environment.DATASOURCE, datasourceName);
setUnlessNull(props, Environment.DIALECT, dialect);
if ( cacheProviderClass == null )
{
cacheProviderClass = "org.hibernate.cache.HashtableCacheProvider";
}
setUnlessNull(props, Environment.CACHE_PROVIDER, cacheProviderClass);
setUnlessNull(props, Environment.CACHE_REGION_PREFIX, cacheRegionPrefix);
setUnlessNull(props, Environment.USE_MINIMAL_PUTS, minimalPutsEnabled);
setUnlessNull(props, Environment.HBM2DDL_AUTO, hbm2ddlAuto);
setUnlessNull(props, Environment.DEFAULT_SCHEMA, defaultSchema);
setUnlessNull(props, Environment.STATEMENT_BATCH_SIZE, jdbcBatchSize);
log.info( "Using JDBC batch size : " + jdbcBatchSize );
setUnlessNull(props, Environment.STATEMENT_FETCH_SIZE, jdbcFetchSize);
setUnlessNull(props, Environment.USE_SCROLLABLE_RESULTSET, jdbcScrollableResultSetEnabled);
setUnlessNull(props, Environment.USE_QUERY_CACHE, queryCacheEnabled);
setUnlessNull(props, Environment.QUERY_SUBSTITUTIONS, querySubstitutions);
setUnlessNull(props, Environment.MAX_FETCH_DEPTH, maxFetchDepth);
setUnlessNull(props, Environment.SHOW_SQL, showSqlEnabled);
setUnlessNull(props, Environment.USE_GET_GENERATED_KEYS, getGeneratedKeysEnabled);
setUnlessNull(props, Environment.USER, username);
setUnlessNull(props, Environment.PASS, password);
setUnlessNull(props, Environment.BATCH_VERSIONED_DATA, batchVersionedDataEnabled);
setUnlessNull(props, Environment.USE_STREAMS_FOR_BINARY, streamsForBinaryEnabled);
setUnlessNull(props, Environment.USE_REFLECTION_OPTIMIZER, reflectionOptimizationEnabled);
setUnlessNull(props, Environment.TRANSACTION_MANAGER_STRATEGY, JBossTransactionManagerLookup.class.getName());
setUnlessNull(props, Environment.TRANSACTION_STRATEGY, JTATransactionFactory.class.getName());
if ( deployedTreeCacheObjectName != null )
{
String objNameString = deployedTreeCacheObjectName.toString();
if ( objNameString != null && !"".equals( objNameString ) )
{
props.setProperty( DeployedTreeCacheProvider.OBJECT_NAME_PROP, objNameString );
}
}
props.setProperty( Environment.FLUSH_BEFORE_COMPLETION, "true" );
props.setProperty( Environment.AUTO_CLOSE_SESSION, "true" );
props.setProperty( Environment.RELEASE_CONNECTIONS, "true" );
return props;
}
private void setUnlessNull(Properties props, String key, String value)
{
if(value != null)
{
props.setProperty(key, value);
}
}
private Interceptor generateInterceptorInstance()
{
if (sessionFactoryInterceptor == null)
{
return null;
}
log.info("Generating session factory interceptor instance [" + sessionFactoryInterceptor + "]");
try
{
return (Interceptor) Thread.currentThread()
.getContextClassLoader()
.loadClass( sessionFactoryInterceptor )
.newInstance();
}
catch(Throwable t)
{
log.warn("Unable to generate session factory interceptor instance", t);
}
return null;
}
private void bind() throws HibernateException
{
InitialContext ctx = null;
try
{
ctx = new InitialContext();
Util.bind( ctx, sessionFactoryName, sessionFactory );
}
catch( NamingException e )
{
throw new HibernateException( "Unable to bind SessionFactory into JNDI", e );
}
finally
{
if ( ctx != null )
{
try
{
ctx.close();
}
catch( Throwable ignore )
{
}
}
}
}
private void unbind() throws HibernateException
{
InitialContext ctx = null;
try
{
ctx = new InitialContext();
Util.unbind( ctx, sessionFactoryName );
}
catch( NamingException e )
{
throw new HibernateException( "Unable to unbind SessionFactory from JNDI", e );
}
finally {
if ( ctx != null )
{
try
{
ctx.close();
}
catch( Throwable ignore )
{
}
}
}
}
private void forceCleanup()
{
try
{
sessionFactory.close();
sessionFactory = null;
}
catch( Throwable ignore )
{
}
}
public String toString()
{
return super.toString() + " [ServiceName=" + serviceName + ", JNDI=" + sessionFactoryName + "]";
}
}