// @TODO Retrieve IDGenerators from the database (via JDBC or
// Hibernate) at initialization and refresh time.
-// @TODO Remove redundancy. If we're using JDBC, a great deal of JDBC code
-// is replicated in each method below.
+// @TODO Handle both CollectionSpace IDs and URIs as identifiers
+// for ID generators, replacing simple integer IDs.
+//
+// We're currently using simple integer IDs to identify ID generators
+// in this initial iteration.
+//
+// To uniquely identify ID generators in production, we'll need to handle
+// both CollectionSpace IDs (csids) - a form of UUIDs/GUIDs - and some
+// other form of identifier to be determined, such as URLs or URNs.
// @TODO Handle concurrency.
//
// a new IDPattern and returning its next ID. As a result,
// the generated IDs may well duplicate other, previously-generated IDs.
//
-// When we start storing ID generators and IDs in a database, the
-// the current ID associated with each generator will be stored
+// When we start storing ID generators and IDs in a database,
+// the state associated with each generator will be stored
// and modified in a single location.
//
-// At that point, we'll also need to add code to handle concurrent requests.
+// At that point, we'll also need to add code to handle concurrent
+// requests to modify that state.
// @TODO Verify access (public, protected, or private) to service methods.
final String DATABASE_USERNAME = "test";
final String DATABASE_PASSWORD = "test";
final String TABLE_NAME = "id_generator";
+
+ boolean hasPreconditions = true;
//////////////////////////////////////////////////////////////////////
/**
// @TODO Decide when and how to fail at startup, or else to correct
// failure conditions automatically, when preconditions are not met.
+ //
+ // Currently, errors at initialization are merely informative and
+ // result in exceptions that can be persistently logged.
+
+ init();
- // init();
}
// @TODO init() and hasTable() are currently UNTESTED as of 2009-08-11T13:00-0700.
* for the service is not present, or is not in its required state.
*/
public void init() throws IllegalStateException {
-
+
+ logger.debug("> in init");
+
+ try {
+ instantiateJdbcDriver(JDBC_DRIVER_CLASSNAME);
+ } catch (IllegalStateException e) {
+ throw e;
+ }
+
try {
boolean hasTable = hasTable(TABLE_NAME);
if (! hasTable) {
- throw new IllegalStateException(
- "Table " + "\'" + TABLE_NAME + "\'" + " could not be found in the database.");
+ String msg =
+ "Required table " +
+ "\'" + TABLE_NAME + "\'" +
+ " could not be found in the database.";
+ logger.warn(msg);
+ throw new IllegalStateException(msg);
}
} catch (IllegalStateException e) {
throw e;
//////////////////////////////////////////////////////////////////////
/**
- * Identifies whether a specified table exists in the database.
+ * Creates a new instance of the specified JDBC driver class.
*
- * @param tablename The name of a database table.
+ * @param jdbcDriverClassname The name of a JDBC driver class.
*
- * @return True if the specified table exists in the database;
- * false if the specified table does not exist in the database.
- *
- * @throws IllegalStateException if an error occurs while checking for the
- * existence of the specified table.
+ * @throws IllegalStateException if a new instance of the specified
+ * JDBC driver class cannot be created.
*/
- public boolean hasTable(String tablename) throws IllegalStateException {
-
- logger.debug("> in hasTable");
-
- if (tablename == null || tablename.equals("")) {
- return false;
- }
+ public void instantiateJdbcDriver(String jdbcDriverClassname)
+ throws IllegalStateException {
+ logger.debug("> in instantiateJdbcDriver(String)");
+
try {
- Class.forName(JDBC_DRIVER_CLASSNAME).newInstance();
+ Class.forName(jdbcDriverClassname).newInstance();
} catch (ClassNotFoundException e) {
throw new IllegalStateException(
"Error finding JDBC driver class '" +
JDBC_DRIVER_CLASSNAME +
"' to set up database connection.");
}
-
+
+ }
+
+ //////////////////////////////////////////////////////////////////////
+ /**
+ * Identifies whether a specified table exists in the database.
+ *
+ * @param tablename The name of a database table.
+ *
+ * @return True if the specified table exists in the database;
+ * false if the specified table does not exist in the database.
+ *
+ * @throws IllegalStateException if an error occurs while checking for the
+ * existence of the specified table.
+ */
+ public boolean hasTable(String tablename) throws IllegalStateException {
+
+ logger.debug("> in hasTable");
+
+ if (tablename == null || tablename.equals("")) {
+ return false;
+ }
+
Connection conn = null;
try {
-
- conn = DriverManager.getConnection(DATABASE_URL, DATABASE_USERNAME, DATABASE_PASSWORD);
- Statement stmt = conn.createStatement();
-
+ conn = getJdbcConnection();
+
+ // Retrieve a list of tables in the current database.
final String CATALOG_NAME = null;
final String SCHEMA_NAME_PATTERN = null;
final String[] TABLE_TYPES = null;
conn.getMetaData().getTables(
CATALOG_NAME, SCHEMA_NAME_PATTERN, tablename, TABLE_TYPES);
+ // Check whether a table with the specified name is in that list.
boolean moreRows = tablesMatchingTableName.next();
if (! moreRows) {
return false;
} catch (SQLException e) {
throw new IllegalStateException(
- "Error while checking for existance of tablebase table: " + e.getMessage());
+ "Error while checking for existence of tablebase table: " + e.getMessage());
} finally {
try {
if (conn != null) {
// @TODO Where relevant, implement logic to check for ID availability,
// after generating a candidate ID.
- // @TODO We're currently using simple integer IDs to identify ID generators
- // in this initial iteration.
- //
- // To uniquely identify ID generators in production, we'll need to handle
- // both CollectionSpace IDs (csids) - a form of UUIDs/GUIDs - and some
- // other form of identifier to be determined, such as URLs or URNs.
- //
// @TODO: Add checks for authorization to perform this operation.
String newId = "";
* @throws IllegalArgumentException if the requested ID generator could not be found.
*
* @throws IllegalStateException if a storage-related error occurred.
- *
- * @TODO: We're currently using simple integer IDs to identify ID generators
- * in this initial iteration.
- *
- * To uniquely identify ID generators in production, we'll need to handle
- * both CollectionSpace IDs (csids) - a form of UUIDs/GUIDs - and some
- * other form of identifier to be determined, such as URLs or URNs.
- *
- * @TODO: Refactor to remove redundant code that this method shares with other
- * database-using methods in this class.
- *
- * @TODO: Add checks for authorization to perform this operation.
*/
public void updateLastID(String csid, String lastId)
throws IllegalArgumentException, IllegalStateException {
logger.debug("> in updateLastID");
- try {
- Class.forName(JDBC_DRIVER_CLASSNAME).newInstance();
- } catch (ClassNotFoundException e) {
- throw new IllegalStateException(
- "Error finding JDBC driver class '" +
- JDBC_DRIVER_CLASSNAME +
- "' to set up database connection.");
- } catch (InstantiationException e) {
- throw new IllegalStateException(
- "Error instantiating JDBC driver class '" +
- JDBC_DRIVER_CLASSNAME +
- "' to set up database connection.");
- } catch (IllegalAccessException e) {
- throw new IllegalStateException(
- "Error accessing JDBC driver class '" +
- JDBC_DRIVER_CLASSNAME +
- "' to set up database connection.");
- }
-
+ // @TODO Where relevant, implement logic to check for ID availability,
+ // after generating a candidate ID.
+
+ // @TODO: Add checks for authorization to perform this operation.
+
Connection conn = null;
try {
- conn = DriverManager.getConnection(DATABASE_URL, DATABASE_USERNAME, DATABASE_PASSWORD);
-
+ conn = getJdbcConnection();
Statement stmt = conn.createStatement();
int rowsUpdated = stmt.executeUpdate(
logger.debug("> in getLastID");
- // @TODO: We're currently using simple integer IDs to identify ID generators
- // in this initial iteration.
- //
- // To uniquely identify ID generators in production, we'll need to handle
- // both CollectionSpace IDs (csids) - a form of UUIDs/GUIDs - and some
- // other form of identifier to be determined, such as URLs or URNs.
- //
- // @TODO: Refactor to remove redundant code that this method shares with other
- // database-using methods in this class.
- //
- // @TODO: Determine whether to add checks for authorization to perform this operation.
+ // @TODO Where relevant, implement logic to check for ID availability,
+ // after generating a candidate ID.
+
+ // @TODO: Add checks for authorization to perform this operation.
String lastId = null;
-
- try {
- Class.forName(JDBC_DRIVER_CLASSNAME).newInstance();
- } catch (ClassNotFoundException e) {
- throw new IllegalStateException(
- "Error finding JDBC driver class '" +
- JDBC_DRIVER_CLASSNAME +
- "' to set up database connection.");
- } catch (InstantiationException e) {
- throw new IllegalStateException(
- "Error instantiating JDBC driver class '" +
- JDBC_DRIVER_CLASSNAME +
- "' to set up database connection.");
- } catch (IllegalAccessException e) {
- throw new IllegalStateException(
- "Error accessing JDBC driver class '" +
- JDBC_DRIVER_CLASSNAME +
- "' to set up database connection.");
- }
-
Connection conn = null;
try {
-
- conn = DriverManager.getConnection(DATABASE_URL, DATABASE_USERNAME, DATABASE_PASSWORD);
+ conn = getJdbcConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(
logger.debug("> in addIDGenerator(String, IDPattern)");
- // @TODO: We're currently using simple integer IDs to identify ID generators
- // in this initial iteration.
- //
- // To uniquely identify ID generators in production, we'll need to handle
- // both CollectionSpace IDs (csids) - a form of UUIDs/GUIDs - and some
- // other form of identifier to be determined, such as URLs or URNs.
-
- // @TODO: Refactor to remove redundant code that this method shares with other
- // database-using methods in this class.
-
// @TODO: Add checks for authorization to perform this operation.
if (pattern == null) {
logger.debug("> in addIDGenerator(String, String)");
- // @TODO We're currently using simple integer IDs to identify ID generators
- // in this initial iteration.
- //
- // To uniquely identify ID generators in production, we'll need to handle
- // both CollectionSpace IDs (csids) - a form of UUIDs/GUIDs - and some
- // other form of identifier to be determined, such as URLs or URNs.
-
- // @TODO Refactor to remove redundant code that this method shares with other
- // database-using methods in this class.
-
// @TODO Add checks for authorization to perform this operation.
if (serializedGenerator == null || serializedGenerator.equals("")) {
"Could not understand or parse this representation of an ID generator.");
}
- try {
- Class.forName(JDBC_DRIVER_CLASSNAME).newInstance();
- } catch (ClassNotFoundException e) {
- throw new IllegalStateException(
- "Error finding JDBC driver class '" +
- JDBC_DRIVER_CLASSNAME +
- "' to set up database connection.");
- } catch (InstantiationException e) {
- throw new IllegalStateException(
- "Error instantiating JDBC driver class '" +
- JDBC_DRIVER_CLASSNAME +
- "' to set up database connection.");
- } catch (IllegalAccessException e) {
- throw new IllegalStateException(
- "Error accessing JDBC driver class '" +
- JDBC_DRIVER_CLASSNAME +
- "' to set up database connection.");
- }
-
Connection conn = null;
try {
- conn = DriverManager.getConnection(DATABASE_URL, DATABASE_USERNAME, DATABASE_PASSWORD);
-
+ conn = getJdbcConnection();
Statement stmt = conn.createStatement();
// Test whether this ID generator already exists in the database.
boolean moreRows = rs.next();
- boolean idPatternFound = true;
+ boolean idGeneratorFound = true;
if (! moreRows) {
- idPatternFound = false;
+ idGeneratorFound = false;
}
// If this ID generator already exists in the database, throw an Exception.
//
// @TODO This exception needs to convey the meaning that a conflict has
// occurred, so that this status can be reported to the client.
- if (idPatternFound) {
+ if (idGeneratorFound) {
throw new IllegalStateException(
"Conflict with existing pattern when attempting to add new ID generator with ID '" +
csid +
"Error adding new ID generator '" + csid + "'" + " to the database.");
}
- } // end if (idPatternFound)
+ } // end if (idGeneratorFound)
logger.debug("> successfully added ID Pattern: " + csid);
* including the values of its constituent parts.
*
* @throws IllegalStateException if a storage-related error occurred.
- *
- * @TODO: We're currently using simple integer IDs to identify ID generators
- * in this initial iteration.
- *
- * To uniquely identify ID generators in production, we'll need to handle
- * both CollectionSpace IDs (csids) - a form of UUIDs/GUIDs - and some
- * other form of identifier to be determined, such as URLs or URNs.
- *
- * @TODO: Refactor to remove redundant code that this method shares with other
- * database-using methods in this class.
- *
- * @TODO: Add checks for authorization to perform this operation.
*/
public void updateIDGenerator(String csid, IDPattern pattern)
throws IllegalArgumentException, IllegalStateException {
logger.debug("> in updateIDGenerator(String, IDPattern)");
+ // @TODO: Add checks for authorization to perform this operation.
+
if (pattern == null) {
throw new IllegalArgumentException(
"ID generator supplied in an attempt to update an existing ID generator cannot be null.");
* including the values of its constituent parts.
*
* @throws IllegalStateException if a storage-related error occurred.
- *
- * @TODO: We're currently using simple integer IDs to identify ID generators
- * in this initial iteration.
- *
- * To uniquely identify ID generators in production, we'll need to handle
- * both CollectionSpace IDs (csids) - a form of UUIDs/GUIDs - and some
- * other form of identifier to be determined, such as URLs or URNs.
- *
- * @TODO: Refactor to remove redundant code that this method shares with other
- * database-using methods in this class.
- *
- * @TODO: Add checks for authorization to perform this operation.
*/
public void updateIDGenerator(String csid, String serializedGenerator)
throws IllegalArgumentException, IllegalStateException {
logger.debug("> in updateIDGenerator(String, String)");
+
+ // @TODO: Add checks for authorization to perform this operation.
if (serializedGenerator == null || serializedGenerator.equals("")) {
throw new IllegalArgumentException(
"Could not understand or parse this representation of an ID generator.");
}
- try {
- Class.forName(JDBC_DRIVER_CLASSNAME).newInstance();
- } catch (ClassNotFoundException e) {
- throw new IllegalStateException(
- "Error finding JDBC driver class '" +
- JDBC_DRIVER_CLASSNAME +
- "' to set up database connection.");
- } catch (InstantiationException e) {
- throw new IllegalStateException(
- "Error instantiating JDBC driver class '" +
- JDBC_DRIVER_CLASSNAME +
- "' to set up database connection.");
- } catch (IllegalAccessException e) {
- throw new IllegalStateException(
- "Error accessing JDBC driver class '" +
- JDBC_DRIVER_CLASSNAME +
- "' to set up database connection.");
- }
-
Connection conn = null;
try {
- conn = DriverManager.getConnection(DATABASE_URL, DATABASE_USERNAME, DATABASE_PASSWORD);
-
+ conn = getJdbcConnection();
Statement stmt = conn.createStatement();
// Test whether this ID generator already exists in the database.
* @param csid An identifier for an ID generator.
*
* @throws IllegalStateException if a storage-related error occurred.
- *
- * @TODO: We're currently using simple integer IDs to identify ID generators
- * in this initial iteration.
- *
- * To uniquely identify ID generators in production, we'll need to handle
- * both CollectionSpace IDs (csids) - a form of UUIDs/GUIDs - and some
- * other form of identifier to be determined, such as URLs or URNs.
- *
- * @TODO: Refactor to remove redundant code that this method shares with other
- * database-using methods in this class.
- *
- * @TODO: Add checks for authorization to perform this operation.
*/
public void deleteIDGenerator(String csid)
throws IllegalArgumentException, IllegalStateException {
logger.debug("> in deleteIDGenerator");
-
- try {
- Class.forName(JDBC_DRIVER_CLASSNAME).newInstance();
- } catch (ClassNotFoundException e) {
- throw new IllegalStateException(
- "Error finding JDBC driver class '" +
- JDBC_DRIVER_CLASSNAME +
- "' to set up database connection.");
- } catch (InstantiationException e) {
- throw new IllegalStateException(
- "Error instantiating JDBC driver class '" +
- JDBC_DRIVER_CLASSNAME +
- "' to set up database connection.");
- } catch (IllegalAccessException e) {
- throw new IllegalStateException(
- "Error accessing JDBC driver class '" +
- JDBC_DRIVER_CLASSNAME +
- "' to set up database connection.");
- }
+
+ // @TODO: Add checks for authorization to perform this operation.
Connection conn = null;
try {
- conn = DriverManager.getConnection(DATABASE_URL, DATABASE_USERNAME, DATABASE_PASSWORD);
-
+ conn = getJdbcConnection();
Statement stmt = conn.createStatement();
// Test whether this ID generator already exists in the database.
}
}
+
+ //////////////////////////////////////////////////////////////////////
+ /**
+ * Opens a connection to the database and returns a JDBC Connection object.
+ *
+ * @return A JDBC database Connection object.
+ *
+ * @throws SQLException if a storage-related error occurred.
+ */
+ public Connection getJdbcConnection() throws SQLException {
+
+ logger.debug("> in getJdbcConnection");
+
+ Connection conn = null;
+ try {
+ conn = DriverManager.getConnection(DATABASE_URL, DATABASE_USERNAME, DATABASE_PASSWORD);
+
+ } catch (SQLException e) {
+ throw e;
+ }
+
+ return conn;
+
+ }
+
//////////////////////////////////////////////////////////////////////
/**
* Returns a requested ID generator from persistent storage.
* @throws IllegalArgumentException if the requested ID generator could not be found.
*
* @throws IllegalStateException if a storage-related error occurred.
- *
- * @TODO: We're currently using simple integer IDs to identify ID generators
- * in this initial iteration.
- *
- * To uniquely identify ID generators in production, we'll need to handle
- * both CollectionSpace IDs (csids) - a form of UUIDs/GUIDs - and some
- * other form of identifier to be determined, such as URLs or URNs.
- *
- * @TODO: Refactor to remove redundant code that this method shares with other
- * database-using methods in this class.
*/
public String getIDGenerator (String csid) throws IllegalArgumentException, IllegalStateException {
String serializedGenerator = null;
- try {
- Class.forName(JDBC_DRIVER_CLASSNAME).newInstance();
- } catch (ClassNotFoundException e) {
- throw new IllegalStateException(
- "Error finding JDBC driver class '" +
- JDBC_DRIVER_CLASSNAME +
- "' to set up database connection.");
- } catch (InstantiationException e) {
- throw new IllegalStateException(
- "Error instantiating JDBC driver class '" +
- JDBC_DRIVER_CLASSNAME +
- "' to set up database connection.");
- } catch (IllegalAccessException e) {
- throw new IllegalStateException(
- "Error accessing JDBC driver class '" +
- JDBC_DRIVER_CLASSNAME +
- "' to set up database connection.");
- }
-
Connection conn = null;
try {
- conn = DriverManager.getConnection(DATABASE_URL, DATABASE_USERNAME, DATABASE_PASSWORD);
-
+ conn = getJdbcConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(