package org.jboss.jdbc;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.Statement;
import javax.management.MBeanRegistration;
import org.jboss.system.ServiceMBeanSupport;
import org.jboss.system.server.ServerConfigLocator;
public class HypersonicDatabase
extends ServiceMBeanSupport
implements HypersonicDatabaseMBean, MBeanRegistration
{
private static final String DEFAULT_PASSWORD = "";
private static final String DEFAULT_USER = "sa";
private static final String JDBC_DRIVER_CLASS = "org.hsqldb.jdbcDriver";
private static final String JDBC_URL_PREFIX = "jdbc:hsqldb:";
private static final String DEFAULT_REMOTE_SHUTDOWN_COMMAND = "SHUTDOWN COMPACT";
private static final String DEFAULT_IN_PROCESS_SHUTDOWN_COMMAND = "SHUTDOWN COMPACT";
private static final String DEFAULT_IN_MEMORY_SHUTDOWN_COMMAND = "SHUTDOWN IMMEDIATELY";
private static final String HYPERSONIC_DATA_DIR = "hypersonic";
private static final int DEFAULT_PORT = 1701;
private static final String DEFAULT_DATABASE_NAME = "default";
private static final String IN_MEMORY_DATABASE = ".";
private static final String DEFAULT_DATABASE_MANAGER_CLASS = "org.hsqldb.util.DatabaseManagerSwing";
private static final String DEFAULT_SERVER_CLASS = "org.hsqldb.Server";
File dbPath;
String name = DEFAULT_DATABASE_NAME;
int port = DEFAULT_PORT;
boolean silent = true;
boolean trace = false;
boolean no_system_exit = true;
boolean persist = true;
String shutdownCommand;
boolean inProcessMode = false;
private String user = DEFAULT_USER;
private String password = DEFAULT_PASSWORD;
private String databaseManagerClass = DEFAULT_DATABASE_MANAGER_CLASS;
private String serverClass = DEFAULT_SERVER_CLASS;
private Thread serverThread;
private Connection connection;
public HypersonicDatabase()
{
}
public void setDatabase(String name)
{
if (name == null)
{
name = DEFAULT_DATABASE_NAME;
}
this.name = name;
}
public String getDatabase()
{
return name;
}
public void setPort(final int port)
{
this.port = port;
}
public int getPort()
{
return port;
}
public void setSilent(final boolean silent)
{
this.silent = silent;
}
public boolean getSilent()
{
return silent;
}
public void setTrace(final boolean trace)
{
this.trace = trace;
}
public boolean getTrace()
{
return trace;
}
public void setNo_system_exit(final boolean no_system_exit)
{
this.no_system_exit = no_system_exit;
}
public boolean getNo_system_exit()
{
return no_system_exit;
}
public void setPersist(final boolean persist)
{
this.persist = persist;
}
public boolean getPersist()
{
return persist;
}
public String getDatabasePath()
{
if (dbPath != null)
{
return dbPath.toString();
}
else
{
return null;
}
}
public boolean isInProcessMode()
{
return inProcessMode;
}
public String getShutdownCommand()
{
return shutdownCommand;
}
public void setInProcessMode(boolean b)
{
inProcessMode = b;
}
public void setShutdownCommand(String string)
{
shutdownCommand = string;
}
public String getPassword()
{
return password;
}
public String getUser()
{
return user;
}
public void setPassword(String password)
{
if (password == null)
{
password = DEFAULT_PASSWORD;
}
this.password = password;
}
public void setUser(String user)
{
if (user == null)
{
user = DEFAULT_USER;
}
this.user = user;
}
public String getDatabaseManagerClass()
{
return databaseManagerClass;
}
public void setDatabaseManagerClass(String databaseManagerClass)
{
if (databaseManagerClass == null)
{
databaseManagerClass = DEFAULT_DATABASE_MANAGER_CLASS;
}
this.databaseManagerClass = databaseManagerClass;
}
public String getServerClass()
{
return serverClass;
}
public void setServerClass(String serverClass)
{
if (serverClass == null)
{
serverClass = DEFAULT_SERVER_CLASS;
}
this.serverClass = serverClass;
}
public void startDatabaseManager()
{
new Thread()
{
public void run()
{
try
{
String driver = JDBC_DRIVER_CLASS;
String[] args;
if (!inProcessMode)
{
args =
new String[] {
"-noexit",
"-driver",
driver,
"-url",
JDBC_URL_PREFIX + "hsql://localhost:" + port,
"-user",
user,
"-password",
password,
"-dir",
getDatabasePath()
};
}
else if (IN_MEMORY_DATABASE.equals(name))
{
args =
new String[] {
"-noexit",
"-driver",
driver,
"-url",
JDBC_URL_PREFIX + IN_MEMORY_DATABASE,
"-user",
user,
"-password",
password
};
}
else
{
args =
new String[] {
"-noexit",
"-driver",
driver,
"-url",
JDBC_URL_PREFIX + getDatabasePath(),
"-user",
user,
"-password",
password,
"-dir",
getDatabasePath()
};
}
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Class clazz = Class.forName(databaseManagerClass, true, cl);
Method main = clazz.getMethod("main", new Class[] { args.getClass() });
main.invoke(null, new Object [] { args });
}
catch (Exception e)
{
log.error("Failed to start database manager", e);
}
}
}
.start();
}
protected void startService() throws Exception
{
if (!persist)
{
inProcessMode = true;
name = IN_MEMORY_DATABASE;
}
if (!inProcessMode)
{
startRemoteDatabase();
}
else if (IN_MEMORY_DATABASE.equals(name))
{
startInMemoryDatabase();
}
else
{
startStandaloneDatabase();
}
}
private void startStandaloneDatabase() throws Exception
{
File dataDir = ServerConfigLocator.locate().getServerDataDir();
File hypersoniDir = new File(dataDir, HYPERSONIC_DATA_DIR);
if (!hypersoniDir.exists())
{
hypersoniDir.mkdirs();
}
if (!hypersoniDir.isDirectory())
{
throw new IOException("Failed to create directory: " + hypersoniDir);
}
dbPath = new File(hypersoniDir, name);
String dbURL = JDBC_URL_PREFIX + getDatabasePath();
connection = getConnection(dbURL);
}
private void startInMemoryDatabase() throws Exception
{
String dbURL = JDBC_URL_PREFIX + IN_MEMORY_DATABASE;
connection = getConnection(dbURL);
}
private void startRemoteDatabase() throws Exception
{
File dataDir = ServerConfigLocator.locate().getServerDataDir();
File hypersoniDir = new File(dataDir, HYPERSONIC_DATA_DIR);
if (!hypersoniDir.exists())
{
hypersoniDir.mkdirs();
}
if (!hypersoniDir.isDirectory())
{
throw new IOException("Failed to create directory: " + hypersoniDir);
}
dbPath = new File(hypersoniDir, name);
serverThread = new Thread("hypersonic-" + name)
{
public void run()
{
try
{
String[] args =
new String[] {
"-database",
dbPath.toString(),
"-port",
String.valueOf(port),
"-silent",
String.valueOf(silent),
"-trace",
String.valueOf(trace),
"-no_system_exit",
String.valueOf(no_system_exit),
};
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Class clazz = Class.forName(serverClass, true, cl);
Method main = clazz.getMethod("main", new Class[] { args.getClass() });
main.invoke(null, new Object[] { args } );
}
catch (Exception e)
{
log.error("Failed to start database", e);
}
}
};
serverThread.start();
}
protected void stopService() throws Exception
{
if (!inProcessMode)
{
stopRemoteDatabase();
}
else if (IN_MEMORY_DATABASE.equals(name))
{
stopInMemoryDatabase();
}
else
{
stopStandaloneDatabase();
}
}
private void stopStandaloneDatabase() throws Exception
{
String dbURL = JDBC_URL_PREFIX + getDatabasePath();
Connection connection = getConnection(dbURL);
Statement statement = connection.createStatement();
String shutdownCommand = this.shutdownCommand;
if (shutdownCommand == null)
{
shutdownCommand = DEFAULT_IN_PROCESS_SHUTDOWN_COMMAND;
}
statement.executeQuery(shutdownCommand);
this.connection = null;
log.info("Database standalone closed clean");
}
private void stopInMemoryDatabase() throws Exception
{
String dbURL = JDBC_URL_PREFIX + IN_MEMORY_DATABASE;
Connection connection = getConnection(dbURL);
Statement statement = connection.createStatement();
String shutdownCommand = this.shutdownCommand;
if (shutdownCommand == null)
{
shutdownCommand = DEFAULT_IN_MEMORY_SHUTDOWN_COMMAND;
}
statement.executeQuery(shutdownCommand);
this.connection = null;
log.info("Database in memory closed clean");
}
private void stopRemoteDatabase() throws Exception
{
String dbURL = JDBC_URL_PREFIX + "hsql://localhost:" + port;
Connection connection = getConnection(dbURL);
Statement statement = connection.createStatement();
String shutdownCommand = this.shutdownCommand;
if (shutdownCommand == null)
{
shutdownCommand = DEFAULT_REMOTE_SHUTDOWN_COMMAND;
}
statement.executeQuery(shutdownCommand);
serverThread = null;
this.connection = null;
log.info("Database remote closed clean");
}
private synchronized Connection getConnection(String dbURL) throws Exception
{
if (connection == null)
{
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Driver d = (Driver) Class.forName(JDBC_DRIVER_CLASS, true, cl).newInstance();
connection = DriverManager.getConnection(dbURL, user, password);
}
return connection;
}
}