package org.jboss.ejb.plugins.keygenerator.hilo;
import org.jboss.system.ServiceMBeanSupport;
import org.jboss.ejb.plugins.keygenerator.KeyGeneratorFactory;
import org.jboss.ejb.plugins.keygenerator.KeyGenerator;
import org.jboss.ejb.plugins.cmp.jdbc.JDBCUtil;
import org.jboss.ejb.plugins.cmp.jdbc.SQLUtil;
import org.jboss.naming.Util;
import org.jboss.deployment.DeploymentException;
import javax.management.ObjectName;
import javax.naming.InitialContext;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.sql.DataSource;
import javax.transaction.TransactionManager;
import java.io.Serializable;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
public class HiLoKeyGeneratorFactory
extends ServiceMBeanSupport
implements KeyGeneratorFactory, HiLoKeyGeneratorFactoryMBean, Serializable
{
static final long serialVersionUID = -8086895827613378739L;
private ObjectName dataSource;
private transient DataSource ds;
private transient TransactionManager tm;
private String jndiName;
private String tableName;
private String sequenceColumn;
private String sequenceName;
private String idColumnName;
private String createTableDdl;
private long blockSize;
public void setFactoryName(String factoryName)
{
this.jndiName = factoryName;
}
public String getFactoryName()
{
return jndiName;
}
public void setDataSource(ObjectName dataSource) throws Exception
{
if(getState() == STARTED && !dataSource.equals(this.dataSource))
{
ds = lookupDataSource(dataSource);
}
this.dataSource = dataSource;
}
public ObjectName getDataSource()
{
return dataSource;
}
public String getTableName()
{
return tableName;
}
public void setTableName(String tableName)
throws Exception
{
if(getState() == STARTED && !tableName.equals(this.tableName))
{
initSequence(tableName, sequenceColumn, sequenceName, idColumnName);
}
this.tableName = tableName;
}
public String getSequenceColumn()
{
return sequenceColumn;
}
public void setSequenceColumn(String sequenceColumn)
{
this.sequenceColumn = sequenceColumn;
}
public String getSequenceName()
{
return sequenceName;
}
public void setSequenceName(String sequenceName)
{
this.sequenceName = sequenceName;
}
public String getIdColumnName()
{
return idColumnName;
}
public void setIdColumnName(String idColumnName)
{
this.idColumnName = idColumnName;
}
public String getCreateTableDdl()
{
return createTableDdl;
}
public void setCreateTableDdl(String createTableDdl)
{
this.createTableDdl = createTableDdl;
}
public long getBlockSize()
{
return blockSize;
}
public void setBlockSize(long blockSize)
{
this.blockSize = blockSize;
}
public KeyGenerator getKeyGenerator() throws Exception
{
return new HiLoKeyGenerator(ds, tableName, sequenceColumn, sequenceName, idColumnName, blockSize, tm);
}
public void startService()
throws Exception
{
Context ctx = new InitialContext();
Util.rebind(ctx, getFactoryName(), this);
tm = (TransactionManager)ctx.lookup("java:/TransactionManager");
ds = lookupDataSource(dataSource);
dropTableIfExists(tableName);
initSequence(tableName, sequenceColumn, sequenceName, idColumnName);
}
public void stopService()
throws Exception
{
ds = null;
tm = null;
Context ctx = new InitialContext();
Util.unbind(ctx, getFactoryName());
}
private void initSequence(String tableName, String sequenceColumn, String sequenceName, String idColumnName)
throws SQLException, DeploymentException
{
createTableIfNotExists(tableName);
Connection con = null;
Statement st = null;
ResultSet rs = null;
try
{
String sql = "select * from " + tableName + " where " + sequenceColumn + "='" + sequenceName + "'";
log.debug("Executing SQL: " + sql);
con = ds.getConnection();
st = con.createStatement();
rs = st.executeQuery(sql);
if(!rs.next())
{
sql = "insert into " +
tableName +
"(" +
sequenceColumn +
", " +
idColumnName +
") values ('" + sequenceName + "', 0)";
log.debug("Executing SQL: " + sql);
final Statement insertSt = con.createStatement();
try
{
final int i = insertSt.executeUpdate(sql);
if(i != 1)
{
throw new SQLException("Expected one updated row but got: " + i);
}
}
finally
{
JDBCUtil.safeClose(insertSt);
}
}
}
finally
{
JDBCUtil.safeClose(rs);
JDBCUtil.safeClose(st);
JDBCUtil.safeClose(con);
}
}
private void createTableIfNotExists(String tableName)
throws SQLException, DeploymentException
{
Connection con = null;
Statement st = null;
try
{
if(!SQLUtil.tableExists(tableName, ds))
{
log.debug("Executing DDL: " + createTableDdl);
con = ds.getConnection();
st = con.createStatement();
st.executeUpdate(createTableDdl);
}
}
finally
{
JDBCUtil.safeClose(st);
JDBCUtil.safeClose(con);
}
}
private void dropTableIfExists(String tableName)
throws SQLException, DeploymentException
{
Connection con = null;
Statement st = null;
try
{
if(SQLUtil.tableExists(tableName, ds))
{
final String ddl = "drop table " + tableName;
log.debug("Executing DDL: " + ddl);
con = ds.getConnection();
st = con.createStatement();
st.executeUpdate(ddl);
}
}
finally
{
JDBCUtil.safeClose(st);
JDBCUtil.safeClose(con);
}
}
private DataSource lookupDataSource(ObjectName dataSource)
throws Exception
{
try
{
String dsJndi = (String) server.getAttribute(dataSource, "BindName");
return (DataSource)new InitialContext().lookup(dsJndi);
}
catch(NamingException e)
{
throw new Exception("Failed to lookup data source: " + dataSource);
}
}
}