uk.ac.ic.doc.automed
Class DSR

java.lang.Object
  extended by uk.ac.ic.doc.automed.DSR
All Implemented Interfaces:
XMLifyConstants
Direct Known Subclasses:
DataSourceRepository

public class DSR
extends java.lang.Object
implements XMLifyConstants

Reads data source definitions from a configuration file and provides methods to get a Connection for a data souce.

Configuration File
The default configuration file "uk.ac.ic.doc.automed.DSR::data_source_repository.cfg" is read and checked for syntax errors when the class is first loaded.
Blank lines (lines containing only white space) are ignored. Comments can appear anywhere, they start with a '#' character and extend to the end of their line. A directive is a line that starts with a keyword (preceeded onlly by white space) which is followed by the keyword's value. The value starts from the first non white space character after the keyword and extends to the end of the line or first comment character. All white space within the value is preserved. Trailing white space and white space between a value and a comment are stripped. Multline values can be specified using '\' as the last, non white space character before the the beginning of a comment or the end of the line. The newlines seperating the lines are preserved.

A data source definition must begin with the DataSource directive. The order of the directives after the DataSource directive is not significant.

Directives

Keyword Argument Type Description
DataSource String The name of the data source for which all directives up to the next DataSouce apply Required
ConnectionType String Currently only type "JDBC" is supported Required
JdbcURL String The JDBC URL used to connect to the data source Required
JdbcDriver String The fully qualified name of the JDBC driver class needed to connect to the data source Required
Username String Username needed to connect to data source Optional
Password String Password needed to connect to data source
Optional
ZeroForNull String A table name and field name seperated by a period. Certain commands such as display and exportdb will use this to convert values of the field to null when they are zero in a result set quering the table. This is get round a bug in the postgresql driver where integer foreign key fields return 0 when their value is null. Optional
SerialID String A table name and field name seperated by a period. A field marked as SerialID will still have it's values written by the exportdb command but the importdb command will not try to set a value for the field when inserting rows. It is assumed that the underlying database will supply values (presumably sequential).
Optional
SerialRef String A table name and field name seperated by a period followed by a colon and another table name and field. The first field marked as a SerialRef should be a field that is a foreign key to the second field named which itself should be a SerialID field. importdb will use the value supplied by the DBS for the SerialID field when inserting the SerialRef field.
Optional

A property can be defined using the same syntax, any unrecognized keyword is interpreted as a property name and the value is assumed to be of type String. The difference between properties and keywords is that keywords are those properties that the DSR "knows about"

Author:
Michael Boyd

Nested Class Summary
 
Nested classes/interfaces inherited from interface uk.ac.ic.doc.automed.xml.XMLifyConstants
XMLifyConstants.IgnoreNextElementException
 
Field Summary
private static java.lang.Class commandClass
          The Class commandClass is reflected upon for getters, setters etc.
private static java.lang.String[][] commandData
          The names of the commands to add using {@link #addCommand(String, Class)
private static java.util.Map commandHelp
           
private static java.util.Map commandParamsHelp
           
private static java.util.Map commands
          (String)Command -> (Method)doCommand(String[]) Maintained by {@link #addCommand(String, Class, String)
private static int CONNECTION_TYPE_JDBC
           
private static int CONNECTION_TYPE_UNKNOWN
           
private static java.util.Map creaters
           
private static java.lang.String currentConfigFile
           
private static java.lang.String currentConfigFileFullPath
           
private static java.util.Map dataSources
          (String)Name -> HashMap of (String)Property -> (Object)Value
private static java.util.Map dbas
          (String)DataSource -> Connection
private static java.lang.String defaultDataSource
          For users of the command line dispatcher to set if they don't want their user to have to specify a data source for each command
private static java.lang.String defaultUserName
           
private static java.util.Map getters
           
private static java.util.Map isers
          (String)Property -> Method
private static java.lang.Object[][] keywordData
          definition of keywords and their types a keyword's type is either null, in which case the keyword takes no argument or it must be Character.class or the class must have a constructor that takes a string argument.
private static java.util.Map keywords
          (String)Keyword -> (Class)Type
private static java.util.List reloadHooks
           
private static java.util.Map removers
           
private static java.util.Map serialIDFields
           
private static java.util.Map serialRefFields
          of (String)DataSource -> HashMap of (String)Table -> HashMap of (String)Field->{(String)Table, (String)Field}
private static java.util.Map setters
           
private static java.util.Map zeroForNullFields
          of (String)DataSource -> HashMap of (String)Table -> HashSet of (String)Field
 
Fields inherited from interface uk.ac.ic.doc.automed.xml.XMLifyConstants
CHARACTERS, CHILDREN, DEFINITIVE, DEFINITIVE_CHILDREN, DEFINITIVE_CHILDREN_RECURSE, DEFINITIVE_MEMBER, DEFINITIVE_MEMBER_AND_CHILDREN, DEFINITIVE_MEMBER_RECURSE, END_DOCUMENT, END_ELEMENT, ERROR, EXCLUDE, EXCLUDE_MEMBER, FATAL_ERROR, FIRSTPASS, IGNORABLE_WHITESPACE, MEMBER, NOTATION_DECL, OBJECT, OBJECT_CHILDREN, OBJECT_CHILDREN_RECURSE, OBJECT_MEMBER, OBJECT_MEMBER_AND_CHILDREN, OBJECT_MEMBER_RECURSE, ONEPASS, PRIMITIVE, PRIMITIVE_CHILDREN, PRIMITIVE_CHILDREN_RECURSE, PRIMITIVE_MEMBER, PRIMITIVE_MEMBER_AND_CHILDREN, PRIMITIVE_MEMBER_RECURSE, PROCESSING_INSTRUCTION, RECURSE, REFERENCE, REFERENCE_CHILDREN, REFERENCE_CHILDREN_RECURSE, REFERENCE_MEMBER, REFERENCE_MEMBER_AND_CHILDREN, REFERENCE_MEMBER_RECURSE, SAX_ERROR, SECONDPASS, START_DOCUMENT, START_ELEMENT, UNPARSED_ENTITY_DECL, WARNING
 
Constructor Summary
DSR()
          Should never be instantiated
 
Method Summary
static java.lang.reflect.Method addCommand(java.lang.String command, java.lang.Class methodClass, java.lang.String help)
          Looks for a public method with the signature doCommand(String[] args) in the class methodClass and adds it to the commands that can be invoked from the CLI.
static void addReloadHook(java.lang.reflect.Method m)
           
private static void checkDataSource(java.util.Map dataSource)
          Checks the syntax of the given data source's directives.
static void close()
          Close all open connections.
static void commit()
          Use this method when auto-commit is set to false
static void dispatchCommand(java.lang.String[] args)
          Invokes the method registered for the command args[0] with #addCommand(String, Class).
static void doCreateCommand(java.lang.String[] args)
           
static void doCreatedbCommand(java.lang.String[] args)
          Reads the property CreateDB property for the data source and executes the value as an update on the databse connection
static void doDefaultCommand(java.lang.String[] args)
           
static void doDisplayCommand(java.lang.String[] args)
           
static void doDropdbCommand(java.lang.String[] args)
           
static void doGetCommand(java.lang.String[] args)
           
private static void doGetSetCreateRemoveCommand(java.lang.String[] args, java.util.Map methods, java.lang.String prefix)
           
static void doHelpCommand(java.lang.String[] args)
           
static void doIsCommand(java.lang.String[] args)
           
static void doPopulatedbCommand(java.lang.String[] args)
           
static void doPrintCommand(java.lang.String[] args)
           
static void doReloadCommand(java.lang.String[] args)
           
static void doRemoveCommand(java.lang.String[] args)
           
static void doSetCommand(java.lang.String[] args)
           
static java.lang.Object executeStatement(java.lang.String dataSource, java.lang.String sql, boolean display)
           
static java.lang.Object executeStatement(java.lang.String dataSource, java.lang.String sql, boolean display, java.util.Set nullifyZeros)
           
static java.lang.Object[] executeStatements(java.lang.String dataSource, java.lang.String sql, boolean display)
           
static java.lang.Object[] executeStatements(java.lang.String dataSource, java.lang.String sql, boolean display, java.util.Set nullifyZeros)
           
private static java.lang.String extractDataSource(java.lang.String[] args)
           
private static java.lang.String extractDataSource(java.lang.String[] args, int start)
           
(package private) static java.sql.Connection getCachedConnectionToDataSource(java.lang.String name)
           
static java.lang.Class getCommandClass()
           
static java.lang.String getConfigFileName()
          Returns the name of the file used for data source definitions.
static java.lang.String getConnectionJDBCURL(java.lang.String connectionName)
          Return the JDBC URL assocaited with a DSR identified by its name
static java.lang.String getConnectionUsername(java.lang.String connectionName)
          Return the username associated with a DSR identified by its name
private static java.lang.String getConnectionValue(java.lang.String connectionName, java.lang.String key)
          Lookup a key value for a connection, as read in from a .cfg file
static java.sql.Connection getDataSourceConnection(java.lang.String name)
          Gets a connection to the named data souce.
static DBAccess getDataSourceConnection(java.lang.String name, java.lang.String username, java.lang.String password)
          Gets a connection to the named data souce.
static java.lang.Object getDataSourceProperty(java.lang.String dataSourceName, java.lang.String propertyName)
          Returns the named property for the named data source as defined in the configuration file.
static DBAccess getDBAccessObject(java.lang.String dsname)
          Return the DBAccess object that manages the connections to a data source
static java.lang.String getDefaultDataSource()
           
static java.lang.String getDefaultUserName()
           
private static java.lang.String getParametersString(java.lang.reflect.Method m)
           
static java.sql.PreparedStatement getPreparedStatement(java.lang.String dsname, java.lang.String sql)
          Create a prepared statement object of the data source.
private static java.lang.String[] getTableNames(java.lang.String dataSourceName)
           
static void main(java.lang.String[] args)
          Provides a simple command line interface to enable the configuration file to be checked.
private static void printDataSource(java.util.HashMap dataSource)
           
private static void printDataSource(java.lang.String dataSource)
           
protected static void readConfigFile()
          Reads the current configuration file.
protected static void readConfigFile(java.lang.String configFile)
          Reads the directives for the data sources defined in configFile.
private static void readConfigFile(java.lang.String configFile, java.util.Map currentDataSource)
           
static void setCommandClass(java.lang.Class c)
           
static void setCommandHelp(java.lang.String[][] commandHelp)
           
static void setConfigFileName(java.lang.String filename)
          Sets the name of the file used for data source defintiions, this resets any data cached in the MDR or STR and invalidates all objects returned by them prior to this call.
static void setDefaultDataSource(java.lang.String name)
           
static void setDefaultUserName(java.lang.String name)
           
static void shutdown()
          Tear down all connections and shutdown embedded databases.
static void testDataSource()
          Useful for auto-start, embedded data source when we just want to load it
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

CONNECTION_TYPE_UNKNOWN

private static final int CONNECTION_TYPE_UNKNOWN
See Also:
Constant Field Values

CONNECTION_TYPE_JDBC

private static final int CONNECTION_TYPE_JDBC
See Also:
Constant Field Values

keywords

private static final java.util.Map keywords
(String)Keyword -> (Class)Type


dataSources

private static final java.util.Map dataSources
(String)Name -> HashMap of (String)Property -> (Object)Value


commands

private static final java.util.Map commands
(String)Command -> (Method)doCommand(String[]) Maintained by {@link #addCommand(String, Class, String)


dbas

private static final java.util.Map dbas
(String)DataSource -> Connection


commandHelp

private static final java.util.Map commandHelp

currentConfigFile

private static java.lang.String currentConfigFile

currentConfigFileFullPath

private static java.lang.String currentConfigFileFullPath

isers

private static java.util.Map isers
(String)Property -> Method


getters

private static java.util.Map getters

setters

private static java.util.Map setters

creaters

private static java.util.Map creaters

removers

private static java.util.Map removers

zeroForNullFields

private static final java.util.Map zeroForNullFields
of (String)DataSource -> HashMap of (String)Table -> HashSet of (String)Field


serialIDFields

private static final java.util.Map serialIDFields

serialRefFields

private static final java.util.Map serialRefFields
of (String)DataSource -> HashMap of (String)Table -> HashMap of (String)Field->{(String)Table, (String)Field}


commandParamsHelp

private static final java.util.Map commandParamsHelp

defaultDataSource

private static java.lang.String defaultDataSource
For users of the command line dispatcher to set if they don't want their user to have to specify a data source for each command


defaultUserName

private static java.lang.String defaultUserName

commandClass

private static java.lang.Class commandClass
The Class commandClass is reflected upon for getters, setters etc. for use with the get, is, set, create, remove commands


keywordData

private static final java.lang.Object[][] keywordData
definition of keywords and their types a keyword's type is either null, in which case the keyword takes no argument or it must be Character.class or the class must have a constructor that takes a string argument.


commandData

private static final java.lang.String[][] commandData
The names of the commands to add using {@link #addCommand(String, Class)


reloadHooks

private static java.util.List reloadHooks
Constructor Detail

DSR

DSR()
Should never be instantiated

Method Detail

getDefaultDataSource

public static java.lang.String getDefaultDataSource()

setDefaultDataSource

public static void setDefaultDataSource(java.lang.String name)

getDefaultUserName

public static java.lang.String getDefaultUserName()

setDefaultUserName

public static void setDefaultUserName(java.lang.String name)

setCommandHelp

public static void setCommandHelp(java.lang.String[][] commandHelp)

getCommandClass

public static java.lang.Class getCommandClass()

setCommandClass

public static void setCommandClass(java.lang.Class c)

readConfigFile

protected static void readConfigFile()
                              throws java.io.IOException,
                                     DSRException
Reads the current configuration file. This method is called when the class is loaded with the value "::data_source_repository.cfg". It calls readConfigFile(String) with the name of the last configuration file read.

Throws:
java.io.IOException
DSRException
See Also:
readConfigFile(String configFile)

readConfigFile

protected static void readConfigFile(java.lang.String configFile)
                              throws java.io.IOException,
                                     DSRException
Reads the directives for the data sources defined in configFile. If the file is successfully found, then all current datasource definitions are dropped before reading the config file. The config file can be specified with an absolute path or a path relative to the working directory in which the JVM was started or with :: to specify a file in the same directory as the class file. If no classname is given then the DSR class is used (this is how the default configuration file is found).

Parameters:
configFile - The name of the file to read data source definitions from.
Throws:
java.io.IOException - If there's a problem reading the file.
DSRException - If there's an error in the configuration file.

readConfigFile

private static void readConfigFile(java.lang.String configFile,
                                   java.util.Map currentDataSource)
                            throws java.io.IOException,
                                   DSRException
Throws:
java.io.IOException
DSRException

checkDataSource

private static void checkDataSource(java.util.Map dataSource)
                             throws DSRException
Checks the syntax of the given data source's directives.

Throws:
DSRException

getDataSourceProperty

public static java.lang.Object getDataSourceProperty(java.lang.String dataSourceName,
                                                     java.lang.String propertyName)
                                              throws DSRException
Returns the named property for the named data source as defined in the configuration file.

Throws:
DSRException

getDataSourceConnection

public static java.sql.Connection getDataSourceConnection(java.lang.String name)
                                                   throws java.io.IOException,
                                                          java.sql.SQLException,
                                                          DSRException
Gets a connection to the named data souce. This method calls getDataSourceConnection(String name, String username, String password) supplying as username and password the values defined for the data source or null if they aren't defined.

Throws:
java.io.IOException
java.sql.SQLException
DSRException
See Also:
getDataSourceConnection(String name, String username, String password)

getDBAccessObject

public static DBAccess getDBAccessObject(java.lang.String dsname)
Return the DBAccess object that manages the connections to a data source

Parameters:
dsname -
Returns:

getPreparedStatement

public static java.sql.PreparedStatement getPreparedStatement(java.lang.String dsname,
                                                              java.lang.String sql)
                                                       throws java.sql.SQLException
Create a prepared statement object of the data source.

Parameters:
dsname -
Returns:
Throws:
java.sql.SQLException

getDataSourceConnection

public static DBAccess getDataSourceConnection(java.lang.String name,
                                               java.lang.String username,
                                               java.lang.String password)
                                        throws java.io.IOException,
                                               java.sql.SQLException,
                                               DSRException
Gets a connection to the named data souce. If either the username or password are not supplied (i.e. are null) and are relevant to the connection type then the properties defined for the data source are used. If the data source definition doesn't supply thenm either then the user is prompted for them on the standard input.

Parameters:
name - The name of the data source as defined in the configuration file.
username - The username to use when establishing the connection or null if not required or to use the defined value for the data source or prompt the user if not defined.
password - The password to use when establishing the connection or null if not required or to use the defined value for the data source or to prompt the user if not defined.
Returns:
a Connection to the named data source.
Throws:
java.ioIOException - if there's a problem reading input from the user.
java.sql.SQLException - from the DriverManager.getConnection(String, String, String).
DSRException - if there's no definition for the named data source or the connection type is unknown or (for connection type "JDBC") the JdbcDriver can't be found or doesn't implement Driver.
java.io.IOException

getCachedConnectionToDataSource

static java.sql.Connection getCachedConnectionToDataSource(java.lang.String name)
                                                    throws java.io.IOException,
                                                           java.sql.SQLException,
                                                           DSRException
Throws:
java.io.IOException
java.sql.SQLException
DSRException

close

public static void close()
                  throws DSRException
Close all open connections. In most cases, this mean committing (if necessary) without actually tearing down the connection (i.e. keeps in the pool). Use this method instead of shutdown() when your application is closing but other applications are still using the database!

Throws:
DSRException

commit

public static void commit()
                   throws DSRException
Use this method when auto-commit is set to false

Throws:
DSRException

shutdown

public static void shutdown()
                     throws DSRException
Tear down all connections and shutdown embedded databases. Only use this method when you are sure that no other applications are accessing the database!!

Throws:
DSRException

getConnectionValue

private static java.lang.String getConnectionValue(java.lang.String connectionName,
                                                   java.lang.String key)
                                            throws NotFoundException
Lookup a key value for a connection, as read in from a .cfg file

Throws:
NotFoundException

getConnectionUsername

public static java.lang.String getConnectionUsername(java.lang.String connectionName)
Return the username associated with a DSR identified by its name


getConnectionJDBCURL

public static java.lang.String getConnectionJDBCURL(java.lang.String connectionName)
                                             throws NotFoundException
Return the JDBC URL assocaited with a DSR identified by its name

Throws:
NotFoundException

getTableNames

private static java.lang.String[] getTableNames(java.lang.String dataSourceName)
                                         throws DSRException
Throws:
DSRException

executeStatement

public static java.lang.Object executeStatement(java.lang.String dataSource,
                                                java.lang.String sql,
                                                boolean display)
                                         throws DSRException,
                                                java.io.IOException,
                                                java.sql.SQLException
Throws:
DSRException
java.io.IOException
java.sql.SQLException

executeStatement

public static java.lang.Object executeStatement(java.lang.String dataSource,
                                                java.lang.String sql,
                                                boolean display,
                                                java.util.Set nullifyZeros)
                                         throws DSRException,
                                                java.io.IOException,
                                                java.sql.SQLException
Throws:
DSRException
java.io.IOException
java.sql.SQLException

executeStatements

public static java.lang.Object[] executeStatements(java.lang.String dataSource,
                                                   java.lang.String sql,
                                                   boolean display)
                                            throws DSRException,
                                                   java.io.IOException,
                                                   java.sql.SQLException
Throws:
DSRException
java.io.IOException
java.sql.SQLException

executeStatements

public static java.lang.Object[] executeStatements(java.lang.String dataSource,
                                                   java.lang.String sql,
                                                   boolean display,
                                                   java.util.Set nullifyZeros)
                                            throws DSRException,
                                                   java.io.IOException,
                                                   java.sql.SQLException
Throws:
DSRException
java.io.IOException
java.sql.SQLException

main

public static void main(java.lang.String[] args)
Provides a simple command line interface to enable the configuration file to be checked.


dispatchCommand

public static void dispatchCommand(java.lang.String[] args)
                            throws java.lang.Exception
Invokes the method registered for the command args[0] with #addCommand(String, Class).

Throws:
DSRException - if the command is not registered
java.lang.Exception - the target exception if invoke throghs InvocationTargetException

addCommand

public static java.lang.reflect.Method addCommand(java.lang.String command,
                                                  java.lang.Class methodClass,
                                                  java.lang.String help)
                                           throws java.lang.NoSuchMethodException
Looks for a public method with the signature doCommand(String[] args) in the class methodClass and adds it to the commands that can be invoked from the CLI.

Returns:
The previously registered method for the command, if any
Throws:
java.lang.NoSuchMethodException

doDefaultCommand

public static void doDefaultCommand(java.lang.String[] args)

doHelpCommand

public static void doHelpCommand(java.lang.String[] args)

doPrintCommand

public static void doPrintCommand(java.lang.String[] args)

doReloadCommand

public static void doReloadCommand(java.lang.String[] args)
                            throws java.io.IOException
Throws:
java.io.IOException

doCreatedbCommand

public static void doCreatedbCommand(java.lang.String[] args)
                              throws DSRException,
                                     java.io.IOException,
                                     java.sql.SQLException
Reads the property CreateDB property for the data source and executes the value as an update on the databse connection

Throws:
DSRException
java.io.IOException
java.sql.SQLException

doDropdbCommand

public static void doDropdbCommand(java.lang.String[] args)
                            throws DSRException,
                                   java.io.IOException,
                                   java.sql.SQLException
Throws:
DSRException
java.io.IOException
java.sql.SQLException

doDisplayCommand

public static void doDisplayCommand(java.lang.String[] args)
                             throws DSRException,
                                    java.io.IOException,
                                    java.sql.SQLException
Throws:
DSRException
java.io.IOException
java.sql.SQLException

doPopulatedbCommand

public static void doPopulatedbCommand(java.lang.String[] args)
                                throws DSRException,
                                       java.sql.SQLException,
                                       java.io.IOException
Throws:
DSRException
java.sql.SQLException
java.io.IOException

doIsCommand

public static void doIsCommand(java.lang.String[] args)
                        throws java.lang.Exception
Throws:
java.lang.Exception

doGetCommand

public static void doGetCommand(java.lang.String[] args)
                         throws java.lang.Exception
Throws:
java.lang.Exception

doSetCommand

public static void doSetCommand(java.lang.String[] args)
                         throws java.lang.Exception
Throws:
java.lang.Exception

doCreateCommand

public static void doCreateCommand(java.lang.String[] args)
                            throws java.lang.Exception
Throws:
java.lang.Exception

doRemoveCommand

public static void doRemoveCommand(java.lang.String[] args)
                            throws java.lang.Exception
Throws:
java.lang.Exception

doGetSetCreateRemoveCommand

private static void doGetSetCreateRemoveCommand(java.lang.String[] args,
                                                java.util.Map methods,
                                                java.lang.String prefix)
                                         throws java.lang.Exception
Throws:
java.lang.Exception

getParametersString

private static java.lang.String getParametersString(java.lang.reflect.Method m)

printDataSource

private static void printDataSource(java.lang.String dataSource)

printDataSource

private static void printDataSource(java.util.HashMap dataSource)

extractDataSource

private static java.lang.String extractDataSource(java.lang.String[] args)

extractDataSource

private static java.lang.String extractDataSource(java.lang.String[] args,
                                                  int start)

getConfigFileName

public static java.lang.String getConfigFileName()
Returns the name of the file used for data source definitions.

Returns:
the name of the file used for data source definitions.

setConfigFileName

public static void setConfigFileName(java.lang.String filename)
                              throws java.io.IOException,
                                     DSRException
Sets the name of the file used for data source defintiions, this resets any data cached in the MDR or STR and invalidates all objects returned by them prior to this call. This name is set to ~/.automed/data_source_repository.cfg by default.

Parameters:
filename - the name of the file used for data source definitions.
Throws:
java.io.IOException
DSRException

addReloadHook

public static void addReloadHook(java.lang.reflect.Method m)

testDataSource

public static void testDataSource()
                           throws DSRException
Useful for auto-start, embedded data source when we just want to load it

Throws:
DSRException