From b8b2439721a6c999f4f1a62abc6ce5d30ea38fa9 Mon Sep 17 00:00:00 2001 From: Erik Brakkee Date: Sat, 15 Mar 2008 11:33:30 +0000 Subject: [PATCH] --- .../org/wamblee/persistence/Database.java | 75 +++++ .../wamblee/persistence/DatabaseStarter.java | 106 +++++++ .../wamblee/persistence/DerbyDatabase.java | 285 ++++++++++++++++++ .../wamblee/persistence/OracleDatabase.java | 59 ++++ 4 files changed, 525 insertions(+) create mode 100644 support/src/test/java/org/wamblee/persistence/Database.java create mode 100644 support/src/test/java/org/wamblee/persistence/DatabaseStarter.java create mode 100644 support/src/test/java/org/wamblee/persistence/DerbyDatabase.java create mode 100644 support/src/test/java/org/wamblee/persistence/OracleDatabase.java diff --git a/support/src/test/java/org/wamblee/persistence/Database.java b/support/src/test/java/org/wamblee/persistence/Database.java new file mode 100644 index 00000000..eb98a6d2 --- /dev/null +++ b/support/src/test/java/org/wamblee/persistence/Database.java @@ -0,0 +1,75 @@ +/* + * Copyright 2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.wamblee.persistence; + +import java.sql.Connection; +import java.sql.SQLException; + + +/** + * Represents a database. + */ +public interface Database { + /** + * Starts a database. This call should not block and return + * as soon as the database has been started. + * @throws Exception + */ + void start( ) throws Exception; + + /** + * Gets the Jdbc Url to connect to this database. + * @return Jdbc Url. + */ + String getJdbcUrl( ); + + /** + * Gets the external Jdbc URL to connect to this database from other JVMs. + */ + String getExternalJdbcUrl(); + + /** + * Gets the driver class name used to connect to the database from another JVM. + * @return Driver class name. + */ + String getDriverClassName(); + + /** + * Gets the username to connect to the database. + * @return username. + */ + String getUsername(); + + /** + * Gets the password to connect to the database. + * @return password. + */ + String getPassword(); + + /** + * Creates a new database connection. It is the caller's + * responsibility to close this connection. + * + * @return Newly created database connection. + */ + Connection createConnection( ) throws SQLException; + + /** + * Stops a database. + * @throws Exception + */ + void stop( ) throws Exception; +} diff --git a/support/src/test/java/org/wamblee/persistence/DatabaseStarter.java b/support/src/test/java/org/wamblee/persistence/DatabaseStarter.java new file mode 100644 index 00000000..c0bdcc2f --- /dev/null +++ b/support/src/test/java/org/wamblee/persistence/DatabaseStarter.java @@ -0,0 +1,106 @@ +/* + * Copyright 2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.wamblee.persistence; + + +/** + * This class is used for starting the database from ant. + */ +public class DatabaseStarter { + + /** + * Database class which encapsulates management of the database. + */ + private Class _databaseClass; + + /** + * Execution as a main program. Commandline + * + *
+     * 
+     *    DatabaseStarter <databaseClassName>
+     *  
+     * 
+ * + * where the database class name must be the name of a concrete subclass of + * {@link Database}. + * + * @param args + */ + public static void main( String[] args ) throws Exception { + String clazz = args[0]; + try { + new DatabaseStarter( Class.forName( clazz ) ).start( ); + } catch ( Exception e ) { + e.printStackTrace( ); + System.out + .println( "\nUsage: ant -Ddatabase=Derby|Hypersonic startdb" ); + } + } + + /** + * Constructs the database starter. + * + * @param aClassName + * Classname of the database class to use. + * @throws Exception + */ + public DatabaseStarter( Class aClass ) throws Exception { + if ( !Database.class.isAssignableFrom( aClass ) ) { + throw new IllegalArgumentException( "Class '" + + aClass.getName( ) + + "' is not a subclass of Database" ); + } + _databaseClass = aClass; + } + + /** + * Constructs a database starter with the derby database. + * + * @throws Exception + */ + public DatabaseStarter( ) throws Exception { + this( DerbyDatabase.class ); + } + + /** + * Starts the database. + * + * @throws Exception + */ + public void start( ) throws Exception { + Database lDatabase = (Database) _databaseClass.newInstance( ); + lDatabase.start( ); + System.out.println( "Database has been started. " ); + System.out.println( ); + System.out.println("======================================================="); + System.out.println( "Connection details:" ); + System.out.println( " Driver class: " + + lDatabase.getDriverClassName( ) ); + System.out.println( " JDBC URL: " + + lDatabase.getExternalJdbcUrl( ) ); + System.out.println( " username: '" + lDatabase.getUsername( ) + + "'" ); + System.out.println( " password: '" + lDatabase.getPassword( ) + + "'" ); + System.out.println( "Interrupt the program to stop the database." ); + System.out.println("======================================================="); + System.out.println("You must now populate the database with a schema. Use 'ant help' for information."); + for ( ;; ) { + Thread.sleep( 1000 ); + } + } +} diff --git a/support/src/test/java/org/wamblee/persistence/DerbyDatabase.java b/support/src/test/java/org/wamblee/persistence/DerbyDatabase.java new file mode 100644 index 00000000..1385defd --- /dev/null +++ b/support/src/test/java/org/wamblee/persistence/DerbyDatabase.java @@ -0,0 +1,285 @@ +/* + * Copyright 2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.wamblee.persistence; + +import java.io.File; +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.Properties; + +import junit.framework.TestCase; + +import org.apache.derby.drda.NetworkServerControl; +import org.apache.derby.jdbc.ClientDriver; +import org.apache.derby.jdbc.EmbeddedDriver; +import org.apache.log4j.Logger; +import org.wamblee.io.FileSystemUtils; + + +/** + * Derby database setup. + * The external JDBC url used to connect to a running instance is + *
+ *     jdbc:derby:net://localhost:1527/testdb 
+ * 
+ * and the driver class is + *
+ *     com.ibm.db2.jcc.DB2Driver
+ * 
+ * The following jars will have to be used + * db2jcc.jar and db2jcc_license_c.jar. + */ +public class DerbyDatabase implements Database { + + /** + * Logger. + */ + private static final Logger LOGGER + = Logger.getLogger( DerbyDatabase.class ); + + /** + * Database user name. + */ + private static final String USERNAME = "sa"; + + /** + * Database password. + */ + private static final String PASSWORD = "123"; + + /** + * Poll interval for the checking the server status. + */ + private static final int POLL_INTERVAL = 100; + + /** + * Maximum time to wait until the server has started or stopped. + */ + private static final int MAX_WAIT_TIME = 10000; + + /** + * Database name to use. + */ + private static final String DATABASE_NAME = "testdb"; + + /** + * Path on the file system where derby files are stored. + */ + private static final String DATABASE_PATH = "target/db/persistence/derby"; + + /** + * Derby property required to set the file system path + * {@link #DATABASE_PATH}. + */ + private static final String SYSTEM_PATH_PROPERTY = "derby.system.home"; + + /** + * Constructs derby database class to allow creation of derby + * database instances. + */ + public DerbyDatabase( ) { + // Empty + } + + /* + * (non-Javadoc) + * @see org.wamblee.persistence.Database#start() + */ + public void start( ) throws Exception { + // just in case a previous run was killed without the + // cleanup + cleanPersistentStorage( ); + + // set database path. + Properties lProperties = System.getProperties( ); + lProperties.put( SYSTEM_PATH_PROPERTY, DATABASE_PATH ); + + Class.forName( "org.apache.derby.jdbc.EmbeddedDriver" ).newInstance( ); + + runDatabase( ); + + waitUntilStartedOrStopped( true ); + + // Force creation of the database. + Connection lConnection = createConnection( ); + lConnection.close( ); + } + + /** + * Waits until the database server has started or stopped. + * + * @param aStarted + * If true, waits until the server is up, if false, waits until + * the server is down. + * @throws InterruptedException + */ + private void waitUntilStartedOrStopped( boolean aStarted ) + throws InterruptedException { + long lWaited = 0; + + while ( aStarted != isStarted( ) ) { + Thread.sleep( POLL_INTERVAL ); + lWaited += POLL_INTERVAL; + + if ( lWaited > MAX_WAIT_TIME ) { + throw new RuntimeException( + "Derby database did not start within " + MAX_WAIT_TIME + + "ms" ); + } + } + } + + /** + * Checks if the database server has started or not. + * + * @return True if started, false otherwise. + */ + private boolean isStarted( ) { + try { + getControl( ).ping( ); + + return true; + } catch ( Exception e ) { + return false; + } + } + + /** + * Gets the controller for the database server. + * + * @return Controller. + * @throws Exception + */ + private NetworkServerControl getControl( ) throws Exception { + return new NetworkServerControl( ); + } + + /** + * Runs the database. + * + */ + private void runDatabase( ) { + try { + getControl( ).start( new PrintWriter( System.out ) ); + } catch ( Exception e ) { + throw new RuntimeException( e ); + } + } + + /* + * (non-Javadoc) + * @see org.wamblee.persistence.Database#getJdbcUrl() + */ + public String getJdbcUrl( ) { + return getBaseJdbcUrl( ) + + ";create=true;retrieveMessagesFromServerOnGetMessage=true;"; + } + + private String getBaseJdbcUrl( ) { + return "jdbc:derby:" + DATABASE_NAME; + } + + /* + * (non-Javadoc) + * @see org.wamblee.persistence.Database#getExternalJdbcUrl() + */ + public String getExternalJdbcUrl( ) { + return "jdbc:derby:net://localhost:1527/" + DATABASE_NAME; + } + + /** + * Shuts down the derby database and cleans up all created files. + * + */ + private void shutdownDerby( ) { + try { + DriverManager.getConnection( "jdbc:derby:;shutdown=true" ); + throw new RuntimeException( + "Derby did not shutdown, " + + " should always throw exception at shutdown" ); + } catch ( Exception e ) { + LOGGER.info( "Derby has been shut down." ); + } + } + + /* + * (non-Javadoc) + * @see org.wamblee.persistence.Database#getDriverClassName() + */ + public String getDriverClassName( ) { + return ClientDriver.class.getName(); + } + + /** + * Gets the user name. + */ + public String getUsername( ) { + return USERNAME; + } + + /** + * Gets the password. + * @return + */ + public String getPassword( ) { + return PASSWORD; + } + + /* + * (non-Javadoc) + * @see org.wamblee.persistence.Database#createConnection() + */ + public Connection createConnection( ) throws SQLException { + Connection c = + DriverManager.getConnection( getJdbcUrl( ), getUsername( ), + getPassword( ) ); + + return c; + } + + /** + * Stops the derby database and cleans up all derby files. + */ + public void stop( ) throws Exception { + // shutdown network server. + getControl( ).shutdown( ); + waitUntilStartedOrStopped( false ); + + // shutdown inmemory access. + shutdownDerby( ); + cleanPersistentStorage( ); + } + + /** + * Cleans up persistent storage of Derby. + */ + private void cleanPersistentStorage( ) { + File lFile = new File( DATABASE_PATH ); + + if ( lFile.isFile( ) ) { + TestCase.fail( "A regular file by the name " + DATABASE_PATH + + " exists, clean this up first" ); + } + + if ( !lFile.isDirectory( ) ) { + return; // no-op already cleanup up. + } + + FileSystemUtils.deleteDirRecursively( DATABASE_PATH ); + } +} diff --git a/support/src/test/java/org/wamblee/persistence/OracleDatabase.java b/support/src/test/java/org/wamblee/persistence/OracleDatabase.java new file mode 100644 index 00000000..a091dbcb --- /dev/null +++ b/support/src/test/java/org/wamblee/persistence/OracleDatabase.java @@ -0,0 +1,59 @@ +/* + * Copyright 2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.wamblee.persistence; + +import java.sql.Connection; +import java.sql.SQLException; + +public class OracleDatabase implements Database { + + public OracleDatabase() { + super(); + } + + public void start( ) throws Exception { + System.out.println("Oracle must be started externally"); + } + + public String getJdbcUrl( ) { + return null; + } + + public String getExternalJdbcUrl( ) { + return null; + } + + public String getDriverClassName( ) { + return null; + } + + public String getUsername( ) { + return null; + } + + public String getPassword( ) { + return null; + } + + public Connection createConnection( ) throws SQLException { + return null; + } + + public void stop( ) throws Exception { + System.out.println("Oracle must be stopped externally"); + } + +} -- 2.31.1