code: package it.unibz.inf.ontop.answering.connection.pool.impl;
  
  import com.google.inject.Inject;
  import it.unibz.inf.ontop.injection.OntopSystemSQLSettings;
  import it.unibz.inf.ontop.answering.connection.pool.JDBCConnectionPool;
  import org.apache.tomcat.jdbc.pool.DataSource;
  import org.apache.tomcat.jdbc.pool.PoolProperties;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  import java.sql.Connection;
  import java.sql.SQLException;
  import java.util.function.Function;
  
  
  /**
   * Not a SINGLETON!
   */
  public class TomcatConnectionPool implements JDBCConnectionPool {
  
      private static final Logger LOGGER = LoggerFactory.getLogger(TomcatConnectionPool.class);
      private final DataSource tomcatPool;
  
      @Inject
      private TomcatConnectionPool(OntopSystemSQLSettings settings) {
          PoolProperties poolProperties = new PoolProperties();
          poolProperties.setDbProperties(settings.getAdditionalJDBCProperties());
          poolProperties.setUrl(settings.getJdbcUrl());
          poolProperties.setDriverClassName(settings.getJdbcDriver());
          settings.getJdbcUser()
                  .ifPresent(poolProperties::setUsername);
          settings.getJdbcPassword()
                  .ifPresent(poolProperties::setPassword);
          poolProperties.setJmxEnabled(true);
  
          // TEST connection before using it
          boolean keepAlive = settings.isKeepAliveEnabled();
          poolProperties.setTestOnBorrow(keepAlive);
          if (keepAlive) {
              // TODO: refactor this
              String driver = settings.getJdbcDriver();
              if (driver.contains("oracle"))
                  poolProperties.setValidationQuery("select 1 from dual");
              else if (driver.contains("db2"))
                  poolProperties.setValidationQuery("select 1 from sysibm.sysdummy1");
              else
                  poolProperties.setValidationQuery("select 1");
          }
  
          boolean removeAbandoned = settings.isRemoveAbandonedEnabled();
          int abandonedTimeout = settings.getConnectionTimeout();
          int startPoolSize = settings.getConnectionPoolInitialSize();
          int maxPoolSize = settings.getConnectionPoolMaxSize();
          int timeout = settings.getConnectionTimeout();
  
          poolProperties.setTestOnReturn(false);
          poolProperties.setMaxActive(maxPoolSize);
          poolProperties.setMaxIdle(maxPoolSize);
          poolProperties.setInitialSize(startPoolSize);
          poolProperties.setMaxWait(timeout);
          poolProperties.setRemoveAbandonedTimeout(abandonedTimeout);
          poolProperties.setMinEvictableIdleTimeMillis(timeout);
          poolProperties.setLogAbandoned(false);
          poolProperties.setRemoveAbandoned(removeAbandoned);
          poolProperties.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"
                  + "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");
          tomcatPool = new DataSource();
          tomcatPool.setPoolProperties(poolProperties);
  
          LOGGER.debug("Connection Pool Properties:");
          LOGGER.debug("Start size: " + startPoolSize);
          LOGGER.debug("Max size: " + maxPoolSize);
          LOGGER.debug("Remove abandoned connections: " + removeAbandoned);
      }
  
      @Override
      public void close() {
          tomcatPool.close();
      }
  
      @Override
      public Connection getConnection() throws SQLException {
          return tomcatPool.getConnection();
      }
  }
  