PooledDatasourceHelper { public static PoolingDataSource setupPooledDataSource( IDatabaseConnection databaseConnection ) throws DBDatasourceServiceException { PoolingDataSource poolingDataSource = null; String driverClass = null; String url = null; try { if ( databaseConnection.getAccessType().equals( DatabaseAccessType.JNDI ) ) { throw new DBDatasourceServiceException( Messages.getInstance().getErrorString( "PooledDatasourceHelper.ERROR_0008_UNABLE_TO_POOL_DATASOURCE_IT_IS_JNDI", databaseConnection.getName() ) ); } ICacheManager cacheManager = PentahoSystem.getCacheManager( null ); IDatabaseDialectService databaseDialectService = PentahoSystem.get( IDatabaseDialectService.class ); if ( databaseDialectService == null ) { throw new DBDatasourceServiceException( Messages.getInstance().getErrorString( "PooledDatasourceHelper.ERROR_0005_UNABLE_TO_POOL_DATASOURCE_NO_DIALECT_SERVICE", databaseConnection.getName() ) ); } IDatabaseDialect dialect = databaseDialectService.getDialect( databaseConnection ); if ( dialect == null || dialect.getDatabaseType() == null ) { throw new DBDatasourceServiceException( Messages.getInstance().getErrorString( "PooledDatasourceHelper.ERROR_0004_UNABLE_TO_POOL_DATASOURCE_NO_DIALECT", databaseConnection.getName() ) ); } if ( databaseConnection.getDatabaseType().getShortName().equals( "GENERIC" ) ) { driverClass = databaseConnection.getAttributes().get( GenericDatabaseDialect.ATTRIBUTE_CUSTOM_DRIVER_CLASS ); if ( StringUtils.isEmpty( driverClass ) ) { throw new DBDatasourceServiceException( Messages.getInstance().getErrorString( "PooledDatasourceHelper.ERROR_0006_UNABLE_TO_POOL_DATASOURCE_NO_CLASSNAME", databaseConnection.getName() ) ); } } else { driverClass = dialect.getNativeDriver(); if ( StringUtils.isEmpty( driverClass ) ) { throw new DBDatasourceServiceException( Messages.getInstance().getErrorString( "PooledDatasourceHelper.ERROR_0007_UNABLE_TO_POOL_DATASOURCE_NO_DRIVER", databaseConnection.getName() ) ); } } try { url = dialect.getURLWithExtraOptions( databaseConnection ); } catch ( DatabaseDialectException e ) { url = null; } String maxdleConn = PentahoSystem.getSystemSetting( "dbcp-defaults/max-idle-conn", null ); String minIdleConn = PentahoSystem.getSystemSetting( "dbcp-defaults/min-idle-conn", null ); String maxActConn = PentahoSystem.getSystemSetting( "dbcp-defaults/max-act-conn", null ); String validQuery = null; String whenExhaustedAction = PentahoSystem.getSystemSetting( "dbcp-defaults/when-exhausted-action", null ); String wait = PentahoSystem.getSystemSetting( "dbcp-defaults/wait", null ); String testWhileIdleValue = PentahoSystem.getSystemSetting( "dbcp-defaults/test-while-idle", null ); String testOnBorrowValue = PentahoSystem.getSystemSetting( "dbcp-defaults/test-on-borrow", null ); String testOnReturnValue = PentahoSystem.getSystemSetting( "dbcp-defaults/test-on-return", null ); boolean testWhileIdle = !StringUtil.isEmpty( testWhileIdleValue ) ? Boolean.parseBoolean( testWhileIdleValue ) : false; boolean testOnBorrow = !StringUtil.isEmpty( testOnBorrowValue ) ? Boolean.parseBoolean( testOnBorrowValue ) : false; boolean testOnReturn = !StringUtil.isEmpty( testOnReturnValue ) ? Boolean.parseBoolean( testOnReturnValue ) : false; int maxActiveConnection = !StringUtil.isEmpty( maxActConn ) ? Integer.parseInt( maxActConn ) : -1; long waitTime = !StringUtil.isEmpty( wait ) ? Integer.parseInt( wait ) : -1; byte whenExhaustedActionType = !StringUtil.isEmpty( whenExhaustedAction ) ? Byte.parseByte( whenExhaustedAction ) : GenericObjectPool.WHEN_EXHAUSTED_BLOCK; int minIdleConnection = !StringUtil.isEmpty( minIdleConn ) ? Integer.parseInt( minIdleConn ) : -1; int maxIdleConnection = !StringUtil.isEmpty( maxdleConn ) ? Integer.parseInt( maxdleConn ) : -1; Map<String, String> attributes = databaseConnection.getConnectionPoolingProperties(); if ( attributes.containsKey( IDBDatasourceService.MAX_ACTIVE_KEY ) && NumberUtils.isNumber( attributes.get( IDBDatasourceService.MAX_ACTIVE_KEY ) ) ) { maxActiveConnection = Integer.parseInt( attributes.get( IDBDatasourceService.MAX_ACTIVE_KEY ) ); } if ( attributes.containsKey( IDBDatasourceService.MAX_WAIT_KEY ) && NumberUtils.isNumber( attributes.get( IDBDatasourceService.MAX_WAIT_KEY ) ) ) { waitTime = Integer.parseInt( attributes.get( IDBDatasourceService.MAX_WAIT_KEY ) ); } if ( attributes.containsKey( IDBDatasourceService.MIN_IDLE_KEY ) && NumberUtils.isNumber( attributes.get( IDBDatasourceService.MIN_IDLE_KEY ) ) ) { minIdleConnection = Integer.parseInt( attributes.get( IDBDatasourceService.MIN_IDLE_KEY ) ); } if ( attributes.containsKey( IDBDatasourceService.MAX_IDLE_KEY ) && NumberUtils.isNumber( attributes.get( IDBDatasourceService.MAX_IDLE_KEY ) ) ) { maxIdleConnection = Integer.parseInt( attributes.get( IDBDatasourceService.MAX_IDLE_KEY ) ); } if ( attributes.containsKey( IDBDatasourceService.QUERY_KEY ) ) { validQuery = attributes.get( IDBDatasourceService.QUERY_KEY ); } if ( attributes.containsKey( IDBDatasourceService.TEST_ON_BORROW ) ) { testOnBorrow = Boolean.parseBoolean( attributes.get( IDBDatasourceService.TEST_ON_BORROW ) ); } if ( attributes.containsKey( IDBDatasourceService.TEST_ON_RETURN ) ) { testOnReturn = Boolean.parseBoolean( attributes.get( IDBDatasourceService.TEST_ON_RETURN ) ); } if ( attributes.containsKey( IDBDatasourceService.TEST_WHILE_IDLE ) ) { testWhileIdle = Boolean.parseBoolean( attributes.get( IDBDatasourceService.TEST_WHILE_IDLE ) ); } poolingDataSource = new PoolingDataSource(); if ( dialect instanceof IDriverLocator ) { if ( !( (IDriverLocator) dialect ).initialize( driverClass ) ) { throw new DriverNotInitializedException( Messages.getInstance() .getErrorString( "PooledDatasourceHelper.ERROR_0009_UNABLE_TO_POOL_DATASOURCE_CANT_INITIALIZE", databaseConnection.getName(), driverClass ) ); } } else { Class.forName( driverClass ); } GenericObjectPool pool = new GenericObjectPool( null ); if ( attributes.containsKey( IDBDatasourceService.REMOVE_ABANDONED ) && true == Boolean.parseBoolean( attributes.get( IDBDatasourceService.REMOVE_ABANDONED ) ) ) { AbandonedConfig config = new AbandonedConfig(); config.setRemoveAbandoned( Boolean.parseBoolean( attributes.get( IDBDatasourceService.REMOVE_ABANDONED ) ) ); if ( attributes.containsKey( IDBDatasourceService.LOG_ABANDONED ) ) { config.setLogAbandoned( Boolean.parseBoolean( attributes.get( IDBDatasourceService.LOG_ABANDONED ) ) ); } if ( attributes.containsKey( IDBDatasourceService.REMOVE_ABANDONED_TIMEOUT ) && NumberUtils.isNumber( attributes.get( IDBDatasourceService.REMOVE_ABANDONED_TIMEOUT ) ) ) { config.setRemoveAbandonedTimeout( Integer.parseInt( attributes .get( IDBDatasourceService.REMOVE_ABANDONED_TIMEOUT ) ) ); } pool = new AbandonedObjectPool( null, config ); } pool.setWhenExhaustedAction( whenExhaustedActionType ); pool.setMaxActive( maxActiveConnection ); pool.setMaxIdle( maxIdleConnection ); pool.setMaxWait( waitTime ); pool.setMinIdle( minIdleConnection ); pool.setTestWhileIdle( testWhileIdle ); pool.setTestOnReturn( testOnReturn ); pool.setTestOnBorrow( testOnBorrow ); pool.setTestWhileIdle( testWhileIdle ); if ( attributes.containsKey( IDBDatasourceService.TIME_BETWEEN_EVICTION_RUNS_MILLIS ) && NumberUtils.isNumber( attributes.get( IDBDatasourceService.TIME_BETWEEN_EVICTION_RUNS_MILLIS ) ) ) { pool.setTimeBetweenEvictionRunsMillis( Long.parseLong( attributes .get( IDBDatasourceService.TIME_BETWEEN_EVICTION_RUNS_MILLIS ) ) ); } ConnectionFactory factory = getConnectionFactory( databaseConnection, url ); boolean defaultReadOnly = attributes.containsKey( IDBDatasourceService.DEFAULT_READ_ONLY ) ? Boolean.parseBoolean( attributes .get( IDBDatasourceService.TEST_WHILE_IDLE ) ) : false; boolean defaultAutoCommit = attributes.containsKey( IDBDatasourceService.DEFAULT_AUTO_COMMIT ) ? Boolean.parseBoolean( attributes .get( IDBDatasourceService.DEFAULT_AUTO_COMMIT ) ) : true; KeyedObjectPoolFactory kopf = null; if ( attributes.containsKey( IDBDatasourceService.POOL_PREPARED_STATEMENTS ) && true == Boolean.parseBoolean( attributes.get( IDBDatasourceService.POOL_PREPARED_STATEMENTS ) ) ) { int maxOpenPreparedStatements = -1; if ( attributes.containsKey( IDBDatasourceService.MAX_OPEN_PREPARED_STATEMENTS ) && NumberUtils.isNumber( attributes.get( IDBDatasourceService.MAX_OPEN_PREPARED_STATEMENTS ) ) ) { maxOpenPreparedStatements = Integer.parseInt( attributes.get( IDBDatasourceService.MAX_OPEN_PREPARED_STATEMENTS ) ); } kopf = new GenericKeyedObjectPoolFactory( null, pool.getMaxActive(), pool.getWhenExhaustedAction(), pool .getMaxWait(), pool.getMaxIdle(), maxOpenPreparedStatements ); } PoolableConnectionFactory pcf = new PoolableConnectionFactory( factory, pool, kopf, validQuery, defaultReadOnly, defaultAutoCommit ); if ( attributes.containsKey( IDBDatasourceService.DEFAULT_TRANSACTION_ISOLATION ) && !IDBDatasourceService.TRANSACTION_ISOLATION_NONE_VALUE.equalsIgnoreCase( attributes .get( IDBDatasourceService.DEFAULT_TRANSACTION_ISOLATION ) ) ) { Isolation isolationLevel = Isolation.valueOf( attributes.get( IDBDatasourceService.DEFAULT_TRANSACTION_ISOLATION ) ); if ( isolationLevel != null ) { pcf.setDefaultTransactionIsolation( isolationLevel.value() ); } } if ( attributes.containsKey( IDBDatasourceService.DEFAULT_CATALOG ) ) { pcf.setDefaultCatalog( attributes.get( IDBDatasourceService.DEFAULT_CATALOG ) ); } Logger.debug( PooledDatasourceHelper.class, "Pool defaults to " + maxActiveConnection + " max active/" + maxIdleConnection + "max idle" + "with " + waitTime + "wait time" + " idle connections." ); String prePopulatePoolStr = PentahoSystem.getSystemSetting( "dbcp-defaults/pre-populate-pool", null ); if ( Boolean.parseBoolean( prePopulatePoolStr ) ) { for ( int i = 0; i < maxIdleConnection; ++i ) { pool.addObject(); } if ( Logger.getLogLevel() <= ILogger.DEBUG ) { Logger.debug( PooledDatasourceHelper.class, "Pool has been pre-populated with " + maxIdleConnection + " connections" ); } } Logger.debug( PooledDatasourceHelper.class, "Pool now has " + pool.getNumActive() + " active/" + pool.getNumIdle() + " idle connections." ); poolingDataSource.setPool( pool ); if ( attributes.containsKey( IDBDatasourceService.ACCESS_TO_UNDERLYING_CONNECTION_ALLOWED ) ) { poolingDataSource.setAccessToUnderlyingConnectionAllowed( Boolean.parseBoolean( attributes .get( IDBDatasourceService.ACCESS_TO_UNDERLYING_CONNECTION_ALLOWED ) ) ); } cacheManager.putInRegionCache( IDBDatasourceService.JDBC_POOL, databaseConnection.getName(), pool ); return ( poolingDataSource ); } catch ( Exception e ) { throw new DBDatasourceServiceException( e ); } }  static PoolingDataSource setupPooledDataSource( IDatabaseConnection databaseConnection ); static DataSource convert( IDatabaseConnection databaseConnection ); static DataSource getJndiDataSource( final String dsName );  }
@Test public void testSetupPooledDataSourceForJNDI() { try { IDatabaseConnection databaseConnection = mock( IDatabaseConnection.class ); when( databaseConnection.getAccessType() ).thenReturn( DatabaseAccessType.JNDI ); PooledDatasourceHelper.setupPooledDataSource( databaseConnection ); fail( "Expecting the exception to be thrown" ); } catch ( DBDatasourceServiceException ex ) { assertNotNull( ex ); } }
@Test public void testCreatePoolNoDialectService() throws Exception { DatabaseDialectService dialectService = new DatabaseDialectService( false ); final DatabaseTypeHelper databaseTypeHelper = new DatabaseTypeHelper( dialectService.getDatabaseTypes() ); final DatabaseConnection con = new DatabaseConnection(); con.setId( "Postgres" ); con.setName( "Postgres" ); con.setAccessType( DatabaseAccessType.NATIVE ); con.setDatabaseType( databaseTypeHelper.getDatabaseTypeByShortName( "GENERIC" ) ); con.setUsername( "pentaho_user" ); con.setPassword( "password" ); final HashMap<String, String> attrs = new HashMap<>(); attrs.put( DatabaseConnection.ATTRIBUTE_CUSTOM_DRIVER_CLASS, "org.postgresql.Driver" ); attrs.put( DatabaseConnection.ATTRIBUTE_CUSTOM_URL, "jdbc:postgresql: con.setAttributes( attrs ); try { PooledDatasourceHelper.setupPooledDataSource( con ); fail( "Expecting the exception to be thrown" ); } catch ( DBDatasourceServiceException ex ) { assertNotNull( ex ); } }
@Test public void testCreatePoolNoDialect() throws Exception { DatabaseDialectService dialectService = new DatabaseDialectService( false ); mp = new MicroPlatform( SOLUTION_PATH ); mp.defineInstance( IDatabaseDialectService.class, dialectService ); mp.start(); final DatabaseConnection con = new DatabaseConnection(); con.setId( "Postgres" ); con.setName( "Postgres" ); con.setAccessType( DatabaseAccessType.NATIVE ); con.setUsername( "pentaho_user" ); con.setPassword( "password" ); final HashMap<String, String> attrs = new HashMap<>(); attrs.put( DatabaseConnection.ATTRIBUTE_CUSTOM_DRIVER_CLASS, "" ); attrs.put( DatabaseConnection.ATTRIBUTE_CUSTOM_URL, "jdbc:postgresql: con.setAttributes( attrs ); try { PooledDatasourceHelper.setupPooledDataSource( con ); fail( "Expecting the exception to be thrown" ); } catch ( DBDatasourceServiceException ex ) { assertNotNull( ex ); } }
@Test public void testCreatePoolNoClassName() throws Exception { DatabaseDialectService dialectService = new DatabaseDialectService( false ); final DatabaseTypeHelper databaseTypeHelper = new DatabaseTypeHelper( dialectService.getDatabaseTypes() ); mp = new MicroPlatform( SOLUTION_PATH ); mp.defineInstance( IDatabaseDialectService.class, dialectService ); mp.start(); final DatabaseConnection con = new DatabaseConnection(); con.setId( "Postgres" ); con.setName( "Postgres" ); con.setAccessType( DatabaseAccessType.NATIVE ); con.setDatabaseType( databaseTypeHelper.getDatabaseTypeByShortName( "GENERIC" ) ); con.setUsername( "pentaho_user" ); con.setPassword( "password" ); final HashMap<String, String> attrs = new HashMap<>(); attrs.put( DatabaseConnection.ATTRIBUTE_CUSTOM_DRIVER_CLASS, "" ); attrs.put( DatabaseConnection.ATTRIBUTE_CUSTOM_URL, "jdbc:postgresql: con.setAttributes( attrs ); try { PooledDatasourceHelper.setupPooledDataSource( con ); fail( "Expecting the exception to be thrown" ); } catch ( DBDatasourceServiceException ex ) { assertNotNull( ex ); } }