From: <mwl...@us...> - 2009-12-17 20:09:08
|
Revision: 993 http://cishell.svn.sourceforge.net/cishell/?rev=993&view=rev Author: mwlinnem Date: 2009-12-17 20:09:00 +0000 (Thu, 17 Dec 2009) Log Message: ----------- Changed to create entirely new databases (not just new data sources) for each new database datamanager item. Not compatible with previous version. Still in development, but uploading so Patrick can use it in his algorithm as is. Modified Paths: -------------- trunk/core/org.cishell.reference.service.database/META-INF/MANIFEST.MF trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DerbyDatabaseService.java trunk/core/org.cishell.service.database/META-INF/MANIFEST.MF trunk/core/org.cishell.service.database/src/org/cishell/service/database/DatabaseService.java Added Paths: ----------- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/ExternalDatabase.java trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/InternalDerbyDatabase.java trunk/core/org.cishell.service.database/src/org/cishell/service/database/Database.java Removed Paths: ------------- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DataSourceWithIDImpl.java Modified: trunk/core/org.cishell.reference.service.database/META-INF/MANIFEST.MF =================================================================== --- trunk/core/org.cishell.reference.service.database/META-INF/MANIFEST.MF 2009-12-16 17:21:31 UTC (rev 992) +++ trunk/core/org.cishell.reference.service.database/META-INF/MANIFEST.MF 2009-12-17 20:09:00 UTC (rev 993) @@ -13,7 +13,11 @@ org.apache.derby.jdbc, org.cishell.framework.algorithm;version="1.0.0", org.cishell.service.database, + org.eclipse.core.internal.runtime, org.osgi.framework;version="1.4.0", + org.osgi.service.cm;version="1.2.0", org.osgi.service.component;version="1.0.0", - org.osgi.service.log;version="1.3.0" + org.osgi.service.log;version="1.3.0", + org.osgi.util.tracker;version="1.3.3" Service-Component: OSGI-INF/component.xml +Require-Bundle: org.junit4 Deleted: trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DataSourceWithIDImpl.java =================================================================== --- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DataSourceWithIDImpl.java 2009-12-16 17:21:31 UTC (rev 992) +++ trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DataSourceWithIDImpl.java 2009-12-17 20:09:00 UTC (rev 993) @@ -1,79 +0,0 @@ -package org.cishell.reference.service.database; - -import java.io.PrintWriter; -import java.sql.Connection; -import java.sql.SQLException; - -import javax.sql.DataSource; - -import org.cishell.service.database.DataSourceWithID; - -public class DataSourceWithIDImpl implements DataSource, DataSourceWithID { - private static int idCounter = 0; - - private DataSource wrappedDataSource; - private int id; - - private static int generateNewID() { - int newID = idCounter; - - idCounter++; - - return newID; - } - - public DataSourceWithIDImpl(DataSource wrappedDataSource) { - this.wrappedDataSource = wrappedDataSource; - this.id = generateNewID(); - } - - /* (non-Javadoc) - * @see org.cishell.service.database.DataSourceWithIDI#getID() - */ - public int getID() { - return id; - } - - /* (non-Javadoc) - * @see org.cishell.service.database.DataSourceWithIDI#getConnection() - */ - public Connection getConnection() throws SQLException { - return this.wrappedDataSource.getConnection(); - } - - /* (non-Javadoc) - * @see org.cishell.service.database.DataSourceWithIDI#getConnection(java.lang.String, java.lang.String) - */ - public Connection getConnection(String username, String password) - throws SQLException { - return this.wrappedDataSource.getConnection(username, password); - } - - /* (non-Javadoc) - * @see org.cishell.service.database.DataSourceWithIDI#getLogWriter() - */ - public PrintWriter getLogWriter() throws SQLException { - return this.wrappedDataSource.getLogWriter(); - } - - /* (non-Javadoc) - * @see org.cishell.service.database.DataSourceWithIDI#setLogWriter(java.io.PrintWriter) - */ - public void setLogWriter(PrintWriter out) throws SQLException { - this.wrappedDataSource.setLogWriter(out); - } - - /* (non-Javadoc) - * @see org.cishell.service.database.DataSourceWithIDI#getLoginTimeout() - */ - public int getLoginTimeout() throws SQLException { - return this.wrappedDataSource.getLoginTimeout(); - } - - /* (non-Javadoc) - * @see org.cishell.service.database.DataSourceWithIDI#setLoginTimeout(int) - */ - public void setLoginTimeout(int seconds) throws SQLException { - this.wrappedDataSource.setLoginTimeout(seconds); - } -} \ No newline at end of file Modified: trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DerbyDatabaseService.java =================================================================== --- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DerbyDatabaseService.java 2009-12-16 17:21:31 UTC (rev 992) +++ trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DerbyDatabaseService.java 2009-12-17 20:09:00 UTC (rev 993) @@ -2,11 +2,12 @@ import java.sql.Connection; import java.sql.DatabaseMetaData; -import java.sql.DriverManager; import java.sql.ResultSet; -import java.sql.SQLException; import java.sql.Statement; +import java.util.ArrayList; import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; import javax.sql.DataSource; @@ -17,73 +18,57 @@ import org.apache.commons.pool.KeyedObjectPoolFactory; import org.apache.commons.pool.impl.GenericKeyedObjectPoolFactory; import org.apache.commons.pool.impl.GenericObjectPool; -import org.cishell.service.database.DataSourceWithID; +import org.cishell.service.database.Database; import org.cishell.service.database.DatabaseCreationException; import org.cishell.service.database.DatabaseService; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; - public class DerbyDatabaseService implements DatabaseService, BundleActivator { - /* - * Variables used to connect to the internal derby database - * - * TODO: Eventually support connecting databases other than derby, - * and connecting to databases other than our internal one - * (maybe not by modifying this class directly though). - */ - private static final String DERBY_DRIVER_NAME = + public static final String DERBY_DRIVER_NAME = "org.apache.derby.jdbc.EmbeddedDriver"; - private static final String DERBY_PROTOCOL = "jdbc:derby:"; - private static final String DEFAULT_CREATE_CONNECTION_STRING = ";create=true"; - private static final String DEFAULT_SHUTDOWN_CONNECTION_STRING =";shutdown=true"; - private static final String DEFAULT_DB_NAME = "cishell_database"; + public static final String DERBY_PROTOCOL = "jdbc:derby:"; + public static final String DEFAULT_CREATE_CONNECTION_STRING = ";create=true"; + public static final String DEFAULT_SHUTDOWN_CONNECTION_STRING =";shutdown=true"; //where the database exists on the filesystem (relative to the application root directory) private static final String DATABASE_DIRECTORY = "database/"; - //(new connections to the database will come from a pool of connections, improving performance) - private PoolingDataSource poolingDataSource = null; - //hold on to our service registration so we can unregister when this plugin stops. private ServiceRegistration databaseServiceRegistration; + private List internalDatabases = new ArrayList(); + public void start(BundleContext context) throws Exception { /* * Tell Derby to look for an existing database or create a new database - * in the default directory (within our application's directory) + * in the default directory (within our application's directory) */ System.setProperty("derby.system.home", DATABASE_DIRECTORY); - /* - * Make sure we don't have any leftover cruft in the db from previous sessions. - * This is our second chance, if the database wasn't properly cleaned out - * in the stop() method on application exit. - * TODO: If we ever implement some kind of persistence we may not want to do this so bluntly - */ - removeAllNonSystemDatabaseTables(); - //allow the database service to be found by other services/plugins databaseServiceRegistration = context.registerService (DatabaseService.class.getName(), this, new Hashtable()); - } public void stop(BundleContext context) { //disallow the database service to be found by other services/plugins this.databaseServiceRegistration.unregister(); - //try to clean out the database and shut it down. + //try to clean out the databases and shut them down. try { - removeAllNonSystemDatabaseTables(); - String shutdownDatabaseCommand = - DERBY_PROTOCOL + DEFAULT_SHUTDOWN_CONNECTION_STRING; - DriverManager.getConnection(shutdownDatabaseCommand); + + + for (Iterator it = internalDatabases.iterator(); it.hasNext();) { + InternalDerbyDatabase activeDatabase = (InternalDerbyDatabase) it.next(); + Connection activeDatabaseConnection = activeDatabase.getConnection(); + removeAllNonSystemDatabaseTables(activeDatabaseConnection); + activeDatabase.shutdown(); + } } catch (Exception e) { String message = "An unexpected exception occurred while shutting down the internal database." + @@ -92,22 +77,86 @@ throw new RuntimeException(message, e); } } + - //Return a link to a "database" that cannot interfere with other "databases" in the system. - //TODO: May need to refactor to improve the terminology used surrounding this functionality. - public DataSourceWithID createDatabase() throws DatabaseCreationException { - return new DataSourceWithIDImpl(getDataSource()); + private static final String DB_NAME_PREFIX = "cishell_database"; + private static int id = 0; + + public synchronized Database createNewDatabase() throws DatabaseCreationException { + try { + //connect to and create a 'new' database + String databaseName = DB_NAME_PREFIX + id; + Database db = new InternalDerbyDatabase(databaseName, createNewInternalDataSource(databaseName)); + + //if this database existed on disk from a previous session, clean it to be like new + removeAllNonSystemDatabaseTables(db.getConnection()); + + //keep track of our new database for this CIShell session + internalDatabases.add(db); + + id++; + return db; + } catch (Exception e) { + throw new DatabaseCreationException(e); + } } + public Database connectToExistingDatabase(String driver, String url) + throws DatabaseCreationException { + return connectToExistingDatabase(driver, url, null, null); + } + public Database connectToExistingDatabase( + String driver, String url, String username, String password) + throws DatabaseCreationException { + DataSource dataSource = + createNewDataSource(driver, url, username, password); + //TODO: change Database to support non-derby urls and whatnot + Database db = new ExternalDatabase(dataSource); + //(assuming we don't need to keep track of these databases, as we will not close them on shutdown) + return db; + } + + + + //***---UTILITIES---*** + + private DataSource createNewDataSource( + String driver, String url, String username, String password) + throws DatabaseCreationException { + try { + //Load the database driver + Class.forName(driver); + + ConnectionFactory connectionFactory = new DriverManagerConnectionFactory + (url, username, password); + GenericObjectPool connectionPool = new GenericObjectPool(); + KeyedObjectPoolFactory stmtPool = new GenericKeyedObjectPoolFactory(null); + //(side-effects) + new PoolableConnectionFactory(connectionFactory, connectionPool, stmtPool, null, false, true); + //(creating the data source this way is probably overkill for our current purposes, + //(but I don't imagine it does much harm either). + DataSource dataSource = new PoolingDataSource(connectionPool); + return dataSource; + } catch (ClassNotFoundException e) { + throw new DatabaseCreationException + ("Database driver '" + driver + "' could not be found", e); + } + } + + private DataSource createNewInternalDataSource(String dbName) + throws DatabaseCreationException { + String newDatabaseConnectionURL = DERBY_PROTOCOL + + dbName + + DEFAULT_CREATE_CONNECTION_STRING; + return createNewDataSource(DERBY_DRIVER_NAME, newDatabaseConnectionURL, null, null); + } + private static final int SCHEMA_NAME_INDEX = 2; private static final int TABLE_NAME_INDEX = 3; private static final String NONSYSTEM_SCHEMA_NAME = "APP"; - private void removeAllNonSystemDatabaseTables() throws Exception { - - DataSource db = getDataSource(); - Connection dbConnection = db.getConnection(); + private void removeAllNonSystemDatabaseTables(Connection dbConnection) throws Exception { DatabaseMetaData dbMetadata = dbConnection.getMetaData(); ResultSet allTableNames = dbMetadata.getTables(null, null, null, null); @@ -124,45 +173,6 @@ removeTables.executeBatch(); } - - //TODO: It could be that we should give everyone different datasources instead of the same one - private PoolingDataSource getDataSource() throws DatabaseCreationException - { - if (this.poolingDataSource == null) { initializePoolingDataSource(); }; - return poolingDataSource; - } - //lazy-load the pooling data source (implicitly creates the initial database connection) - //TODO: Make it more clear where database connection is initially established - private void initializePoolingDataSource() throws DatabaseCreationException { - if (this.poolingDataSource != null) { - return; - } - - try { - //Load the database driver - Class.forName(DERBY_DRIVER_NAME); - - /* - * TODO:We can use this later to check acceptsUrl for better error reporting. - * Driver jdbcDriver = (Driver) Class.forName(driver).newInstance(); - */ - String newDatabaseConnectionURL = DERBY_PROTOCOL + - DEFAULT_DB_NAME + - DEFAULT_CREATE_CONNECTION_STRING; - - ConnectionFactory connectionFactory = new DriverManagerConnectionFactory - (newDatabaseConnectionURL, null, null); - GenericObjectPool connectionPool = new GenericObjectPool(); - KeyedObjectPoolFactory stmtPool = new GenericKeyedObjectPoolFactory(null); - //(side-effects the connection-pool so it gets its connections from the connection factory (I think)) - new PoolableConnectionFactory(connectionFactory, connectionPool, stmtPool, null, false, true); - this.poolingDataSource = new PoolingDataSource(connectionPool); - } - catch (ClassNotFoundException e) { - throw new DatabaseCreationException - ("Database driver '" + DERBY_DRIVER_NAME + "' could not be found", e); - } - } } Added: trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/ExternalDatabase.java =================================================================== --- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/ExternalDatabase.java (rev 0) +++ trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/ExternalDatabase.java 2009-12-17 20:09:00 UTC (rev 993) @@ -0,0 +1,30 @@ +package org.cishell.reference.service.database; + +import java.sql.Connection; +import java.sql.SQLException; + +import javax.sql.DataSource; + +import org.cishell.service.database.Database; + +public class ExternalDatabase implements Database { + + private DataSource dataSource; + + public ExternalDatabase(DataSource dataSource) { + this.dataSource = dataSource; + } + + public Connection getConnection() throws SQLException { + return dataSource.getConnection(); + } + + /* + * TODO: We could store the password from the beginning. + * Will want to discuss security implications here. + */ + public Connection getConnection(String username, String password) + throws SQLException { + return dataSource.getConnection(username, password); + } +} Added: trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/InternalDerbyDatabase.java =================================================================== --- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/InternalDerbyDatabase.java (rev 0) +++ trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/InternalDerbyDatabase.java 2009-12-17 20:09:00 UTC (rev 993) @@ -0,0 +1,34 @@ +package org.cishell.reference.service.database; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + +import javax.sql.DataSource; + +import org.cishell.service.database.Database; + +public class InternalDerbyDatabase implements Database { + + private String name; + private DataSource dataSource; + + public InternalDerbyDatabase(String name, DataSource dataSource) { + this.name = name; + this.dataSource = dataSource; + } + + + public Connection getConnection() throws SQLException { + return this.dataSource.getConnection(); + } + + public void shutdown() throws SQLException { + String shutdownDatabaseCommand = + DerbyDatabaseService.DERBY_PROTOCOL + + DerbyDatabaseService.DEFAULT_SHUTDOWN_CONNECTION_STRING; + DriverManager.getConnection(shutdownDatabaseCommand); + + + } +} Modified: trunk/core/org.cishell.service.database/META-INF/MANIFEST.MF =================================================================== --- trunk/core/org.cishell.service.database/META-INF/MANIFEST.MF 2009-12-16 17:21:31 UTC (rev 992) +++ trunk/core/org.cishell.service.database/META-INF/MANIFEST.MF 2009-12-17 20:09:00 UTC (rev 993) @@ -5,3 +5,4 @@ Bundle-Version: 1.0.0 Bundle-RequiredExecutionEnvironment: J2SE-1.4 Export-Package: org.cishell.service.database +Import-Package: org.apache.commons.dbcp Added: trunk/core/org.cishell.service.database/src/org/cishell/service/database/Database.java =================================================================== --- trunk/core/org.cishell.service.database/src/org/cishell/service/database/Database.java (rev 0) +++ trunk/core/org.cishell.service.database/src/org/cishell/service/database/Database.java 2009-12-17 20:09:00 UTC (rev 993) @@ -0,0 +1,10 @@ +package org.cishell.service.database; + +import java.sql.Connection; +import java.sql.SQLException; + +import org.apache.commons.dbcp.ConnectionFactory; + +public interface Database { + public Connection getConnection() throws SQLException; +} \ No newline at end of file Modified: trunk/core/org.cishell.service.database/src/org/cishell/service/database/DatabaseService.java =================================================================== --- trunk/core/org.cishell.service.database/src/org/cishell/service/database/DatabaseService.java 2009-12-16 17:21:31 UTC (rev 992) +++ trunk/core/org.cishell.service.database/src/org/cishell/service/database/DatabaseService.java 2009-12-17 20:09:00 UTC (rev 993) @@ -1,5 +1,10 @@ package org.cishell.service.database; public interface DatabaseService { - public DataSourceWithID createDatabase() throws DatabaseCreationException; + public Database createNewDatabase() throws DatabaseCreationException; + public Database connectToExistingDatabase(String driver, String url) + throws DatabaseCreationException; + public Database connectToExistingDatabase( + String driver, String url, String username, String password) + throws DatabaseCreationException; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |