Last active
May 30, 2017 12:57
-
-
Save helospark/68e1dbbbe432658ef13cda0bbb5f58e7 to your computer and use it in GitHub Desktop.
Code to implement H2's ";AUTO_SERVER=true" functionality for HSQLDB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package hsql_test; | |
import java.io.BufferedReader; | |
import java.io.File; | |
import java.io.FileInputStream; | |
import java.io.FileNotFoundException; | |
import java.io.FileOutputStream; | |
import java.io.IOException; | |
import java.io.InputStreamReader; | |
import java.io.PrintStream; | |
import java.net.ServerSocket; | |
import java.sql.Connection; | |
import java.sql.DriverManager; | |
import java.sql.SQLException; | |
import java.util.Optional; | |
import org.hsqldb.Server; | |
import org.hsqldb.persist.HsqlProperties; | |
import org.hsqldb.server.ServerAcl.AclFormatException; | |
/** | |
* Code to implement H2's ";AUTO_SERVER=true" functionality for HSQLDB. | |
*/ | |
public class HsqlAutoserverManager { | |
private static final String AUTOSTART_SERVER_FILE_LOCK_POSTFIX = "_autoserver_lock"; | |
private final String databaseFileName; | |
private Optional<Server> ownedServer = Optional.empty(); | |
/** | |
* Constructor. | |
* @param databaseFileName file to create connection to, eq. "D:\\\\dbtest\\database.db" (\ needs escaping) | |
*/ | |
public HsqlAutoserverManager(String databaseFileName) { | |
this.databaseFileName = databaseFileName; | |
} | |
/** | |
* Starts a connection either by starting a new server and connect to it, or find the running server for the given file and connect to it. | |
* TODO proper exception handling | |
* @return JDBC connection, make sure to close it | |
*/ | |
public synchronized Connection createConnection() { | |
System.out.println("Starting Database"); | |
try { | |
String portToConnect; | |
File databasePortFile = new File(databaseFileName + AUTOSTART_SERVER_FILE_LOCK_POSTFIX); | |
if (!databasePortFile.exists()) { | |
portToConnect = startNewServer(); | |
writeServerPortToFile(databasePortFile, portToConnect); | |
} else { | |
portToConnect = readServerPortFromFile(databasePortFile); | |
} | |
return createJdbcHsqlConnectionToPort(portToConnect); | |
} catch (Exception e) { | |
throw new RuntimeException("Unable to create DB connection", e); | |
} | |
} | |
/** | |
* If this JVM started the server, the server will be shut down, otherwise no operation. | |
*/ | |
public synchronized void shutdown() throws SQLException { | |
if (ownedServer.isPresent()) { | |
ownedServer.get().shutdown(); | |
File file = new File(databaseFileName + AUTOSTART_SERVER_FILE_LOCK_POSTFIX); | |
file.delete(); | |
System.out.println("Database shutdown"); | |
} | |
} | |
private String startNewServer() throws IOException, AclFormatException, FileNotFoundException { | |
String randomPortToStartServerServerOn = String.valueOf(findRandomOpenPort()); | |
HsqlProperties properties = createHsqlProperties(randomPortToStartServerServerOn); | |
startServer(properties); | |
return randomPortToStartServerServerOn; | |
} | |
private HsqlProperties createHsqlProperties(String port) { | |
HsqlProperties properties = new HsqlProperties(); | |
properties.setProperty("server.database.0", "file:" + databaseFileName + ";hsqldb.write_delay=false"); | |
properties.setProperty("server.dbname.0", "mydb"); | |
properties.setProperty("server.port", port); | |
return properties; | |
} | |
private void startServer(HsqlProperties p) throws IOException, AclFormatException { | |
Server dserver = new Server(); | |
dserver.setProperties(p); | |
dserver.setLogWriter(null); // can use custom writer | |
dserver.setErrWriter(null); // can use custom writer | |
dserver.start(); | |
ownedServer = Optional.of(dserver); | |
} | |
private String readServerPortFromFile(File file) throws FileNotFoundException, IOException { | |
String portToConnect; | |
BufferedReader is = new BufferedReader(new InputStreamReader(new FileInputStream(file))); | |
portToConnect = is.readLine(); | |
is.close(); | |
return portToConnect; | |
} | |
private void writeServerPortToFile(File file, String port) throws IOException, FileNotFoundException { | |
file.createNewFile(); | |
PrintStream fs = new PrintStream(new FileOutputStream(file)); | |
fs.print(port); | |
fs.close(); | |
} | |
private Integer findRandomOpenPort() throws IOException { | |
try (ServerSocket socket = new ServerSocket(0)) { | |
return socket.getLocalPort(); | |
} | |
} | |
private Connection createJdbcHsqlConnectionToPort(String portToConnect) throws SQLException { | |
String connectionUri = "jdbc:hsqldb:hsql://localhost:" + portToConnect + "/mydb"; | |
System.out.println("Connecting to server: " + connectionUri); | |
return DriverManager.getConnection(connectionUri, "SA", ""); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment