atg.service.jdbc
Class SwitchingDataSource

java.lang.Object
  extended by atg.nucleus.logging.VariableArgumentApplicationLoggingImpl
      extended by atg.nucleus.GenericService
          extended by atg.service.jdbc.SwitchingDataSource
All Implemented Interfaces:
atg.deployment.agent.Switchable, NameContextBindingListener, NameContextElement, NameResolver, AdminableService, ApplicationLogging, atg.nucleus.logging.ApplicationLoggingSender, atg.nucleus.logging.TraceApplicationLogging, VariableArgumentApplicationLogging, ComponentNameResolver, Service, ServiceListener, java.util.EventListener, javax.sql.DataSource

public class SwitchingDataSource
extends GenericService
implements javax.sql.DataSource, atg.deployment.agent.Switchable

A DataSource which can switch between two or more underlying DataSources. All DataSource method calls are passed through to the currentDataSource.


Field Summary
static java.lang.String CLASS_VERSION
          Class version string
 
Fields inherited from class atg.nucleus.GenericService
SERVICE_INFO_KEY
 
Fields inherited from interface atg.nucleus.logging.TraceApplicationLogging
DEFAULT_LOG_TRACE_STATUS
 
Fields inherited from interface atg.nucleus.logging.ApplicationLogging
DEFAULT_LOG_DEBUG_STATUS, DEFAULT_LOG_ERROR_STATUS, DEFAULT_LOG_INFO_STATUS, DEFAULT_LOG_WARNING_STATUS
 
Constructor Summary
SwitchingDataSource()
          Empty constructor
 
Method Summary
 void addSwitchingDataSourceEventListener(atg.service.jdbc.SwitchingDataSourceEventListener l)
          add a listener
 void doStartService()
          Start the service.
 java.sql.Connection getConnection()
          Attempt to establish a database connection
 java.sql.Connection getConnection(java.lang.String pUser, java.lang.String pPassword)
          Attempt to establish a database connection
 javax.sql.DataSource getCurrentDataSource()
          Get the data source currently being used: all DataSource APIs are passed through to the currentDataSource
 java.lang.String getCurrentDataSourceName()
          Get property currentDataSourceName
 ServiceMap getDataSources()
          Get property dataSources, which is map of data source names to DataSource services.
 java.lang.String[] getDataStoreNames()
           
 java.lang.Object[] getDataStores()
           
 java.lang.String getInfoForDataSource(java.lang.String pName)
          Gets an informational String for the dataSource identified by the given pName.
 java.lang.String getInitialDataSourceName()
          Get property initialDataSourceName
 java.lang.Object getLiveDataStore()
          Returns the 'live' data store.
 java.lang.String getLiveDataStoreName()
          Returns the identifier of the 'live' data store.
 int getLoginTimeout()
          Gets the maximum time in seconds that this data source will wait while attempting to connect to a database.
 java.io.PrintWriter getLogWriter()
          Get the log writer for this data source.
 javax.sql.DataSource getNextDataSource()
          Get property nextDataSource, which is the data source that will become the currentDataSource when #performSwitch() is called
 java.lang.String getNextDataSourceName()
          Get property nextDataSourceName
 java.lang.String getPathForDataSource(java.lang.String pName)
          Gets the absolute name of the dataSource identified by the given pName.
 MutableRepository getRepository()
          Get property repository
 java.lang.Object getStagingDataStore()
          Returns the 'staging' data store.
 java.lang.String getStagingDataStoreName()
          Returns the identifier of the 'staging' data store.
 int getSwitchingDataSourceEventListenerCount()
          get the # of listeners
 atg.service.jdbc.SwitchingDataSourceEventListener[] getSwitchingDataSourceEventListeners()
          get a copy of listeners
 java.lang.String getSwitchingDataSourceName()
          Get property switchingDataSourceName
 boolean hasListener(atg.service.jdbc.SwitchingDataSourceEventListener pListener)
          Determine if the specified object is in our listener list
 boolean isAccessBeforeStart()
           
 boolean isWrapperFor(java.lang.Class<?> iface)
          Returns true if this either implements the interface argument or is directly or indirectly a wrapper for an object that does.
 void performSwitch()
          Perform the second and final phase of the switch process.
 void prepareNextDataSource(java.lang.String pName)
          Prepare to use the named data source at the next switch.
 void prepareSwitch()
          Performs whatever preparations are necessary for an impending data store switch.
 void removeSwitchingDataSourceEventListener(atg.service.jdbc.SwitchingDataSourceEventListener l)
          remove a listener
 void revertPrepareSwitch()
          Reverts the preparations done by a call to prepareSwitch().
 void setAccessBeforeStart(boolean pAccessBeforeStart)
           
 void setDataSources(ServiceMap pDataSources)
          Set property dataSources, which is map of data source names to DataSource services.
 void setInitialDataSourceName(java.lang.String pInitialDataSourceName)
          Set property initialDataSourceName
 void setLoginTimeout(int pSeconds)
          Sets the maximum time in seconds that this data source will wait while attempting to connect to a database.
 void setLogWriter(java.io.PrintWriter pWriter)
          Get the log writer for this data source.
 void setRepository(MutableRepository pRepository)
          Set property repository
 void setSwitchingDataSourceName(java.lang.String pSwitchingDataSourceName)
          Set property switchingDataSourceName
<T> T
unwrap(java.lang.Class<T> iface)
          Returns an object that implements the given interface to allow access to non-standard methods, or standard methods not exposed by the proxy.
 
Methods inherited from class atg.nucleus.GenericService
addLogListener, createAdminServlet, doStopService, getAbsoluteName, getAdminServlet, getLoggingForVlogging, getLogListenerCount, getLogListeners, getName, getNameContext, getNucleus, getRoot, getServiceConfiguration, getServiceInfo, isLoggingDebug, isLoggingError, isLoggingInfo, isLoggingTrace, isLoggingWarning, isRunning, logDebug, logDebug, logDebug, logError, logError, logError, logInfo, logInfo, logInfo, logTrace, logTrace, logTrace, logWarning, logWarning, logWarning, nameContextElementBound, nameContextElementUnbound, removeLogListener, resolveName, resolveName, resolveName, resolveName, sendLogEvent, setLoggingDebug, setLoggingError, setLoggingInfo, setLoggingTrace, setLoggingWarning, setNucleus, setServiceInfo, startService, stopService
 
Methods inherited from class atg.nucleus.logging.VariableArgumentApplicationLoggingImpl
vlogDebug, vlogDebug, vlogDebug, vlogDebug, vlogError, vlogError, vlogError, vlogError, vlogInfo, vlogInfo, vlogInfo, vlogInfo, vlogTrace, vlogTrace, vlogTrace, vlogTrace, vlogWarning, vlogWarning, vlogWarning, vlogWarning
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

CLASS_VERSION

public static java.lang.String CLASS_VERSION
Class version string

Constructor Detail

SwitchingDataSource

public SwitchingDataSource()
Empty constructor

Method Detail

getCurrentDataSource

public javax.sql.DataSource getCurrentDataSource()
Get the data source currently being used: all DataSource APIs are passed through to the currentDataSource

Returns:
currentDataSource, guaranteed to not be null if this service started successfully

getCurrentDataSourceName

public java.lang.String getCurrentDataSourceName()
Get property currentDataSourceName

Returns:
currentDataSourceName

setDataSources

public void setDataSources(ServiceMap pDataSources)
Set property dataSources, which is map of data source names to DataSource services.

Parameters:
pDataSources - new value to set

getDataSources

public ServiceMap getDataSources()
Get property dataSources, which is map of data source names to DataSource services.

Returns:
dataSources

setInitialDataSourceName

public void setInitialDataSourceName(java.lang.String pInitialDataSourceName)
Set property initialDataSourceName

Parameters:
pInitialDataSourceName - new value to set

getInitialDataSourceName

public java.lang.String getInitialDataSourceName()
Get property initialDataSourceName

Returns:
initialDataSourceName

getNextDataSource

public javax.sql.DataSource getNextDataSource()
Get property nextDataSource, which is the data source that will become the currentDataSource when #performSwitch() is called

Returns:
nextDataSource, which is guaranteed to not be null if this service started successfully

getNextDataSourceName

public java.lang.String getNextDataSourceName()
Get property nextDataSourceName

Returns:
nextDataSourceName

setRepository

public void setRepository(MutableRepository pRepository)
Set property repository

Parameters:
pRepository - new value to set

getRepository

public MutableRepository getRepository()
Get property repository

Returns:
repository

setSwitchingDataSourceName

public void setSwitchingDataSourceName(java.lang.String pSwitchingDataSourceName)
Set property switchingDataSourceName

Parameters:
pSwitchingDataSourceName - new value to set

getSwitchingDataSourceName

public java.lang.String getSwitchingDataSourceName()
Get property switchingDataSourceName

Returns:
switchingDataSourceName

setAccessBeforeStart

public void setAccessBeforeStart(boolean pAccessBeforeStart)

isAccessBeforeStart

public boolean isAccessBeforeStart()

getPathForDataSource

public java.lang.String getPathForDataSource(java.lang.String pName)
Gets the absolute name of the dataSource identified by the given pName.

Parameters:
pName - name of data source desired
Returns:
the absolutePath of the dataSource identified by pName, or null if either no such dataSource exists, or if we are unable to determine the absolute name.

getInfoForDataSource

public java.lang.String getInfoForDataSource(java.lang.String pName)
Gets an informational String for the dataSource identified by the given pName.

Parameters:
pName - name of data source desired
Returns:
either the URL or the JNDIName of the dataSource identified by pName, or null if either no such dataSource exists, or if we are unable to determine either of there features.

addSwitchingDataSourceEventListener

public void addSwitchingDataSourceEventListener(atg.service.jdbc.SwitchingDataSourceEventListener l)
add a listener


removeSwitchingDataSourceEventListener

public void removeSwitchingDataSourceEventListener(atg.service.jdbc.SwitchingDataSourceEventListener l)
remove a listener


getSwitchingDataSourceEventListeners

public atg.service.jdbc.SwitchingDataSourceEventListener[] getSwitchingDataSourceEventListeners()
get a copy of listeners


getSwitchingDataSourceEventListenerCount

public int getSwitchingDataSourceEventListenerCount()
get the # of listeners


hasListener

public boolean hasListener(atg.service.jdbc.SwitchingDataSourceEventListener pListener)
Determine if the specified object is in our listener list

Parameters:
pListener - listener to look for

prepareNextDataSource

public void prepareNextDataSource(java.lang.String pName)
                           throws java.sql.SQLException
Prepare to use the named data source at the next switch. This is phase one of the switch process: it doesn't change the behavior of the SwitchingDataSource. In addition to setting the "on deck" data source, it sends out an event to notify listeners that a switch is coming.

Parameters:
pName - name of data source we will switch to next
Throws:
java.sql.SQLException - if the supplied name is null or does not refer to a data source we know about

performSwitch

public void performSwitch()
                   throws java.lang.RuntimeException
Perform the second and final phase of the switch process. Make the nextDataSource be the currentDataSource.

We do not allow either next or current to be null, so we leave nextDataSource as-is. This way is it always safe to call this method, but it won't do anything except send an event unless a data source has been prepared.

Specified by:
performSwitch in interface atg.deployment.agent.Switchable
Throws:
java.lang.RuntimeException - if there is a problem switching

doStartService

public void doStartService()
                    throws ServiceException
Start the service.

Overrides:
doStartService in class GenericService
Throws:
ServiceException - id this object was not properly configured before being started

getDataStoreNames

public java.lang.String[] getDataStoreNames()
Specified by:
getDataStoreNames in interface atg.deployment.agent.Switchable

getDataStores

public java.lang.Object[] getDataStores()
Specified by:
getDataStores in interface atg.deployment.agent.Switchable

getLiveDataStoreName

public java.lang.String getLiveDataStoreName()
Returns the identifier of the 'live' data store.

Specified by:
getLiveDataStoreName in interface atg.deployment.agent.Switchable

getLiveDataStore

public java.lang.Object getLiveDataStore()
Returns the 'live' data store.

Specified by:
getLiveDataStore in interface atg.deployment.agent.Switchable

getStagingDataStoreName

public java.lang.String getStagingDataStoreName()
Returns the identifier of the 'staging' data store.

Specified by:
getStagingDataStoreName in interface atg.deployment.agent.Switchable

getStagingDataStore

public java.lang.Object getStagingDataStore()
Returns the 'staging' data store.

Specified by:
getStagingDataStore in interface atg.deployment.agent.Switchable

prepareSwitch

public void prepareSwitch()
                   throws java.lang.Exception
Performs whatever preparations are necessary for an impending data store switch.

Exception is thrown to allow whatever data store native exception that gets thrown to be passed out in tact.

Specified by:
prepareSwitch in interface atg.deployment.agent.Switchable
Throws:
java.lang.Exception

revertPrepareSwitch

public void revertPrepareSwitch()
                         throws java.lang.Exception
Reverts the preparations done by a call to prepareSwitch(). This method is not necessary for implementation but allows a Switchable data store to be cleaned up if a switch must be canceled due to some other error.

Specified by:
revertPrepareSwitch in interface atg.deployment.agent.Switchable
Throws:
java.lang.Exception

getConnection

public java.sql.Connection getConnection()
                                  throws java.sql.SQLException
Attempt to establish a database connection

Specified by:
getConnection in interface javax.sql.DataSource
Returns:
a connection to the database
Throws:
java.sql.SQLException - if a database-access error occurs

getConnection

public java.sql.Connection getConnection(java.lang.String pUser,
                                         java.lang.String pPassword)
                                  throws java.sql.SQLException
Attempt to establish a database connection

Specified by:
getConnection in interface javax.sql.DataSource
Parameters:
pUser - the database user on whose behalf the Connection is being made
pPassword - the user's password
Returns:
a connection to the database
Throws:
java.sql.SQLException - if a database-access error occurs

getLogWriter

public java.io.PrintWriter getLogWriter()
                                 throws java.sql.SQLException
Get the log writer for this data source.

The log writer is a character output stream to which all logging and tracing messages for this data source object instance will be printed. This includes messages printed by the methods of this object, messages printed by methods of other objects manufactured by this object, and so on. Messages printed to a data source specific log writer are not printed to the log writer associated with the java.sql.Drivermanager class. When a DataSource object is created the log writer is initially null, in other words, logging is disabled.

Specified by:
getLogWriter in interface javax.sql.DataSource
Returns:
the log writer for this data source, null if disabled
Throws:
java.sql.SQLException - if a database-access error occurs

setLogWriter

public void setLogWriter(java.io.PrintWriter pWriter)
                  throws java.sql.SQLException
Get the log writer for this data source.

The log writer is a character output stream to which all logging and tracing messages for this data source object instance will be printed. This includes messages printed by the methods of this object, messages printed by methods of other objects manufactured by this object, and so on. Messages printed to a data source specific log writer are not printed to the log writer associated with the java.sql.Drivermanager class. When a DataSource object is created the log writer is initially null, in other words, logging is disabled.

Specified by:
setLogWriter in interface javax.sql.DataSource
Parameters:
the - the new log writer for this data source: to disable, set to null
Throws:
java.sql.SQLException - if a database-access error occurs

getLoginTimeout

public int getLoginTimeout()
                    throws java.sql.SQLException
Gets the maximum time in seconds that this data source will wait while attempting to connect to a database. A value of zero specifies that the timeout is the default system timeout if there is one; otherwise it specifies that there is no timeout. When a DataSource object is created the login timeout is initially zero.

Specified by:
getLoginTimeout in interface javax.sql.DataSource
Parameters:
the - data source login time limit
Throws:
java.sql.SQLException - if a database-access error occurs

setLoginTimeout

public void setLoginTimeout(int pSeconds)
                     throws java.sql.SQLException
Sets the maximum time in seconds that this data source will wait while attempting to connect to a database. A value of zero specifies that the timeout is the default system timeout if there is one; otherwise it specifies that there is no timeout. When a DataSource object is created the login timeout is initially zero.

Specified by:
setLoginTimeout in interface javax.sql.DataSource
Parameters:
the - data source login time limit
Throws:
java.sql.SQLException - if a database-access error occurs

isWrapperFor

public boolean isWrapperFor(java.lang.Class<?> iface)
                     throws java.sql.SQLException
Returns true if this either implements the interface argument or is directly or indirectly a wrapper for an object that does. Returns false otherwise. If this implements the interface then return true, else if this is a wrapper then return the result of recursively calling isWrapperFor on the wrapped object. If this does not implement the interface and is not a wrapper, return false. This method should be implemented as a low-cost operation compared to unwrap so that callers can use this method to avoid expensive unwrap calls that may fail. If this method returns true then calling unwrap with the same argument should succeed.

Currently not implemented.

Parameters:
iface - a Class defining an interface.
Returns:
true if this implements the interface or directly or indirectly wraps an object that does.
Throws:
java.sql.SQLException - if an error occurs while determining whether this is a wrapper for an object with the given interface.
Since:
1.6

unwrap

public <T> T unwrap(java.lang.Class<T> iface)
         throws java.sql.SQLException
Returns an object that implements the given interface to allow access to non-standard methods, or standard methods not exposed by the proxy. If the receiver implements the interface then the result is the receiver or a proxy for the receiver. If the receiver is a wrapper and the wrapped object implements the interface then the result is the wrapped object or a proxy for the wrapped object. Otherwise return the the result of calling unwrap recursively on the wrapped object or a proxy for that result. If the receiver is not a wrapper and does not implement the interface, then an SQLException is thrown.

Currently not implemented.

Parameters:
iface - A Class defining an interface that the result must implement.
Returns:
an object that implements the interface. May be a proxy for the actual implementing object.
Throws:
java.sql.SQLException - If no object found that implements the interface
Since:
1.6