|
From: <mwl...@us...> - 2009-01-26 18:31:16
|
Revision: 856
http://cishell.svn.sourceforge.net/cishell/?rev=856&view=rev
Author: mwlinnem
Date: 2009-01-26 18:31:07 +0000 (Mon, 26 Jan 2009)
Log Message:
-----------
Major code cleanup. Improved error handling.
Modified Paths:
--------------
trunk/core/org.cishell.reference.service.database/META-INF/MANIFEST.MF
Added Paths:
-----------
trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DerbyDatabaseService.java
Removed Paths:
-------------
trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DatabaseServiceImpl.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-01-24 19:34:25 UTC (rev 855)
+++ trunk/core/org.cishell.reference.service.database/META-INF/MANIFEST.MF 2009-01-26 18:31:07 UTC (rev 856)
@@ -4,7 +4,7 @@
Bundle-SymbolicName: org.cishell.reference.service.database
Bundle-Version: 1.0.0
Bundle-RequiredExecutionEnvironment: J2SE-1.4
-Bundle-Activator: org.cishell.reference.service.database.DatabaseServiceImpl
+Bundle-Activator: org.cishell.reference.service.database.DerbyDatabaseService
X-AutoStart: true
Import-Package: org.apache.commons.dbcp,
org.apache.commons.pool,
Deleted: trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DatabaseServiceImpl.java
===================================================================
--- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DatabaseServiceImpl.java 2009-01-24 19:34:25 UTC (rev 855)
+++ trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DatabaseServiceImpl.java 2009-01-26 18:31:07 UTC (rev 856)
@@ -1,183 +0,0 @@
-package org.cishell.reference.service.database;
-
-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.Hashtable;
-
-import javax.sql.DataSource;
-
-import org.apache.commons.dbcp.ConnectionFactory;
-import org.apache.commons.dbcp.DriverManagerConnectionFactory;
-import org.apache.commons.dbcp.PoolableConnectionFactory;
-import org.apache.commons.dbcp.PoolingDataSource;
-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.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 DatabaseServiceImpl implements DatabaseService, BundleActivator {
- /* TODO: These variables should be abstracted out in a Preferences page at some
- point (I guess).
- */
- private static final String DEFAULT_DRIVER_NAME =
- "org.apache.derby.jdbc.EmbeddedDriver";
- private static final String DEFAULT_PROTOCOL = "jdbc:derby:";
- private static final String DEFAULT_CREATE_CONNECTION_STRING = ";create=true";
- private static final String DEFAULT_DB_NAME = "ultra_sasquatch";
-
- //db name must be unique per running instance of the same NWB installation, otherwise they will overlap
- private static int dbNameCounter = 0;
-
- private ServiceRegistration databaseServiceRegistration;
-
- private PoolingDataSource poolingDataSource = null;
- // TODO: Needed? I just want to make sure nothing goes wrong for now.
- private DataSourceWithID myDataSource = null;
-
- private String driver;
-
- public void start(BundleContext context) throws Exception {
- this.driver = DEFAULT_DRIVER_NAME;
-
- System.err.println("starting!");
-
- // Register me as a service! (This doesn't work?)
- databaseServiceRegistration = context.registerService
- (DatabaseService.class.getName(), this, new Hashtable());
-
- ServiceReference ref = context.getServiceReference(DatabaseService.class.getName());
- if (ref == null) {
- System.out.println("REEEEEEEEEEEEEEEEEEEEEEEFFFFFFF IS NUUUUUUUULLLLLLL!!@!(@!(!)!");
- }
- DatabaseService dbService = (DatabaseService) context.getService(ref);
- if (dbService == null) {
- System.out.println("DEEEBEESEERVICE IS NUUUUL!L!@L!@!@!@@!@!@L..1");
- } else {
-
- }
-
- // Get MY data source! It's mine, and you can't have it!
- try {
- myDataSource = createDatabase();
- }
- catch (DatabaseCreationException e) {
- System.err.println(":'( " + e.getMessage());
- throw e;
- }
-
- System.err.println("meep?");
- cleanOutDatabaseTables();
- }
-
- private void cleanOutDatabaseTables() throws Exception {
- //TODO: We need to be cleaning up and starting the DB correctly
- //TODO: Clean this up
- DataSource ds = getDataSource();
- Connection c = ds.getConnection();
- DatabaseMetaData dmd = c.getMetaData();
- ResultSet tableNames = dmd.getTables(null, null, null, null);
- while (tableNames.next()) {
- for (int ii = 1; ii <= tableNames.getMetaData().getColumnCount(); ii++) {
- String tableContents = tableNames.getString(ii);
- System.out.print(tableContents + ", ");
- }
- if (tableNames.getString(2).indexOf("APP") != -1) {
- System.out.println("MAGOOT!");
- Statement s = c.createStatement();
- System.out.println(tableNames.getString(3));
- System.out.println(s.executeUpdate("DROP TABLE APP." + tableNames.getString(3)));
-
- }
- System.out.println("");
- }
- }
-
- public void stop(BundleContext context) throws Exception {
- cleanOutDatabaseTables();
- try {
- DriverManager.getConnection("jdbc:derby:;shutdown=true");
- } catch (Exception e) {
-
- }
- }
-
- // If one hasn't been created yet, create a connection pool and return it.
- private PoolingDataSource getDataSource() throws DatabaseCreationException
- {
- if (poolingDataSource != null)
- return poolingDataSource;
-
- try {
- System.err.println("Loading driver");
- // This loads the database driver.
- Class.forName(DEFAULT_DRIVER_NAME);
-
- // We can use this later to check acceptsUrl for better error reporting.
- // Driver jdbcDriver = (Driver) Class.forName(driver).newInstance();
-
- //TODO: It may exist from before, actually. Fix this.
- String newDatabaseName =
- DEFAULT_DB_NAME;
- String newDatabaseConnectionURL = DEFAULT_PROTOCOL +
- newDatabaseName +
- DEFAULT_CREATE_CONNECTION_STRING;
-
- System.err.println("connection url: " + newDatabaseConnectionURL);
-
- // This connection factory actually uses the loaded database driver to
- // generate connections.
- ConnectionFactory connectionFactory = new DriverManagerConnectionFactory
- (newDatabaseConnectionURL, null, null);
-
- // This is a generic object pool. It must be linked to a poolable
- // object factory (PoolableObjectFactory), which the new
- // PoolableConnectionFactory below is.
- GenericObjectPool connectionPool = new GenericObjectPool();
-
- // Not sure what this does?
- KeyedObjectPoolFactory stmtPool = new GenericKeyedObjectPoolFactory(null);
-
- // This is a poolable object factory (PoolableObjectFactory) used to
- // create connections for an object pool. It is the glue between the
- // connection factory and the object pool.
- // It links itself up to the connect pool inside its constructor, which
- // is why it's not assigned to a variable out here.
- new PoolableConnectionFactory(connectionFactory, connectionPool, stmtPool, null, false, true);
-
- // Finally, create the connection pool.
- poolingDataSource = new PoolingDataSource(connectionPool);
-
- // TODO: Remove this?
- // Make sure we can get a connection from the connection pool.
- try {
- poolingDataSource.getConnection().close();
- }
- catch (SQLException e) {
- throw new DatabaseCreationException
- ("Could not properly initiate database.", e);
- }
- }
- catch (ClassNotFoundException e) {
- throw new DatabaseCreationException
- ("Database driver (" + driver + ") could not be found", e);
- }
-
- return poolingDataSource;
- }
-
- public DataSourceWithID createDatabase() throws DatabaseCreationException {
- return new DataSourceWithIDImpl(getDataSource());
- }
-}
Copied: trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DerbyDatabaseService.java (from rev 853, trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DatabaseServiceImpl.java)
===================================================================
--- trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DerbyDatabaseService.java (rev 0)
+++ trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DerbyDatabaseService.java 2009-01-26 18:31:07 UTC (rev 856)
@@ -0,0 +1,163 @@
+package org.cishell.reference.service.database;
+
+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.Hashtable;
+
+import javax.sql.DataSource;
+
+import org.apache.commons.dbcp.ConnectionFactory;
+import org.apache.commons.dbcp.DriverManagerConnectionFactory;
+import org.apache.commons.dbcp.PoolableConnectionFactory;
+import org.apache.commons.dbcp.PoolingDataSource;
+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.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 =
+ "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_DB_NAME = "cishell_database";
+
+ //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;
+
+ 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)
+ */
+ 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 {
+ removeAllNonSystemDatabaseTables();
+ DriverManager.getConnection("jdbc:derby:;shutdown=true");
+ } catch (Exception e) {
+ String message =
+ "An unexpected exception occurred while shutting down the internal database." +
+ "Aborting database shutdown process." +
+ "Database may not be left in a valid state (but it will probably be okay).";
+ 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 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();
+ DatabaseMetaData dbMetadata = dbConnection.getMetaData();
+ ResultSet allTableNames = dbMetadata.getTables(null, null, null, null);
+
+ Statement removeTables = dbConnection.createStatement();
+
+ while (allTableNames.next()) {
+ if (allTableNames.getString(SCHEMA_NAME_INDEX).indexOf(NONSYSTEM_SCHEMA_NAME) != -1) {
+ String removeTableSQL =
+ "DROP TABLE " +
+ NONSYSTEM_SCHEMA_NAME + "." + allTableNames.getString(TABLE_NAME_INDEX);
+ removeTables.addBatch(removeTableSQL);
+ }
+ }
+
+ 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
+ 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);
+ }
+ }
+}
Property changes on: trunk/core/org.cishell.reference.service.database/src/org/cishell/reference/service/database/DerbyDatabaseService.java
___________________________________________________________________
Added: svn:mergeinfo
+
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|