package com.github.wicketoracle.oracle.ucp; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.github.wicketoracle.exception.NotInstantiableException; import com.github.wicketoracle.oracle.util.CloseResource; import oracle.ucp.UniversalConnectionPoolAdapter; import oracle.ucp.UniversalConnectionPoolException; import oracle.ucp.admin.UniversalConnectionPoolManagerMBean; import oracle.ucp.admin.UniversalConnectionPoolManagerMBeanImpl; import oracle.ucp.jdbc.LabelableConnection; import oracle.ucp.jdbc.PoolDataSource; import oracle.ucp.jdbc.PoolDataSourceFactory; public final class UCPMgr { /** Log */ private static final Logger LOGGER = LoggerFactory.getLogger( UCPMgr.class ); private static UniversalConnectionPoolManagerMBean ucpPoolMgr = null; private static PoolDataSource ucpDataSource = null; /** * This is a non-instantiable utility class. */ protected UCPMgr() throws NotInstantiableException { throw new NotInstantiableException(); } public static PoolDataSource getUCPDataSource() { return ucpDataSource; } public static UniversalConnectionPoolManagerMBean getUCPPoolMgr() { return ucpPoolMgr; } public static void setupUCP ( final int pAbandonedConnectionTimeOut , final String pConnectionFactoryClassName , final String pConnectionPoolName , final String pUrl , final int pInitialPoolSize , final int pMaxCachedStatements ) throws UniversalConnectionPoolException , SQLException { LOGGER.info( "Setup invoked" ); ucpPoolMgr = UniversalConnectionPoolManagerMBeanImpl.getUniversalConnectionPoolManagerMBean(); LOGGER.info( "UniversalConnectionPoolManagerMBeanImpl instance retrieved" ); ucpDataSource = PoolDataSourceFactory.getPoolDataSource(); LOGGER.info( "UCP pool datasource retrieved" ); ucpDataSource.setConnectionFactoryClassName( pConnectionFactoryClassName ); LOGGER.info( "UCP Connection factory class name set -> {}" , pConnectionFactoryClassName ); ucpDataSource.setConnectionPoolName( pConnectionPoolName ); LOGGER.info( "UCP pool name set -> {}" , pConnectionPoolName ); ucpDataSource.setURL( pUrl ); LOGGER.info( "UCP Url set -> {}" , pUrl ); if ( pInitialPoolSize > 0 ) { ucpDataSource.setInitialPoolSize( pInitialPoolSize ); LOGGER.info( "UCP Initial Pool Size set -> {}" , pInitialPoolSize ); } ucpDataSource.setMaxStatements( pMaxCachedStatements ); LOGGER.info( "UCP Maximum cached statements set -> {}" , pMaxCachedStatements ); if ( pAbandonedConnectionTimeOut >= 0 ) { ucpDataSource.setAbandonedConnectionTimeout( pAbandonedConnectionTimeOut ); LOGGER.info( "UCP abandoned connection timeout set -> {}" , pAbandonedConnectionTimeOut ); } ucpPoolMgr.createConnectionPool( ( UniversalConnectionPoolAdapter ) ucpDataSource ); LOGGER.info( "UCP pool created" ); ucpDataSource.registerConnectionLabelingCallback( new UCPConnectionLabellingCallback() ); LOGGER.info( "Connection Labelling Callback handler registered" ); } public static Connection getLabelledConnection( final String pUsername , final String pPassword ) throws SQLException { final String singleQuote = "\""; final String username = singleQuote + pUsername + singleQuote; final String password = singleQuote + pPassword + singleQuote; /* if an existing connection has these labels, then we'll probably use it */ final Properties requestLabels = new Properties(); requestLabels.put( UCPConnectionLabelKey.USERNAME.toString() , pUsername ); LOGGER.debug( "Request oracle connection -> username -> {}" , pUsername ); final Connection dbConn = ucpDataSource.getConnection( username , password , requestLabels ); LOGGER.debug( "Successfully acquired oracle connection -> username -> {}" , pUsername ); final LabelableConnection lDbConn = ( LabelableConnection ) dbConn; if ( lDbConn.getConnectionLabels() == null ) { LOGGER.debug( "Connection does not have any labels applied" ); final String dbStatement = " BEGIN " + " SYS.dbms_application_info.set_module ( module_name => ? , action_name => ? ); " + " app_utility.pk_session_utility.pr_configure_session( p_client_info => ? ); " + " END; "; CallableStatement dbCstmt = null; try { dbConn.setAutoCommit( false ); LOGGER.debug( "Autocommit set to false" ); dbCstmt = dbConn.prepareCall( dbStatement ); dbCstmt.setString( 1 , "PK_SESSION_UTILITY" ); dbCstmt.setString( 2 , "PR_CONFIGURE_SESSION" ); dbCstmt.setString( 3 , "Oracle/Wicket webapp" ); dbCstmt.execute(); LOGGER.debug( "Configuration stored procedure executed" ); lDbConn.applyConnectionLabel( UCPConnectionLabelKey.USERNAME.toString() , pUsername ); LOGGER.debug( "Connection labels applied" ); } catch ( SQLException sqle ) { LOGGER.error ( "SQL Exception whilst configuring connection -> {}; error code -> {}; sql state -> {}; username ->{}" , new Object [ ] { sqle.getMessage() , sqle.getErrorCode() , sqle.getSQLState() , pUsername } ); throw sqle; } finally { CloseResource.close( dbCstmt ); } } return dbConn; } /** * Do a run time configuration of the application's Universal Connection Pool * * @param pMinPoolSize * @param pMaxPoolSize * @throws SQLException */ public static void configure ( final int pMinPoolSize , final int pMaxPoolSize , final int pMaxCachedStatements ) throws SQLException { ucpDataSource.setMinPoolSize( pMinPoolSize ); ucpDataSource.setMaxPoolSize( pMaxPoolSize ); ucpDataSource.setMaxStatements( pMaxCachedStatements ); } }