/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.commons.dbcp2;

import static org.junit.Assert.fail;

import java.sql.Connection;

import javax.sql.DataSource;

import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.junit.Test;

/**
 * This test *must* execute before all other tests to be effective as it tests
 * the initialisation of DriverManager.
 * Based on the test case for DBCP-212 written by Marcos Sanz
 *
 * @version $Id$
 */
public class TestDriverManagerConnectionFactory {

    @Test
    public void testDriverManagerInit() throws Exception {
        System.setProperty("jdbc.drivers",
                "org.apache.commons.dbcp2.TesterDriver");
        GenericObjectPoolConfig config = new GenericObjectPoolConfig();
        config.setMaxTotal(10);
        config.setMaxIdle(0);
        final ConnectionFactory connectionFactory =
            new DriverManagerConnectionFactory(
                    "jdbc:apache:commons:testdriver",
                    "foo", "bar");
        final PoolableConnectionFactory poolableConnectionFactory =
            new PoolableConnectionFactory(connectionFactory, null);
        poolableConnectionFactory.setDefaultReadOnly(Boolean.FALSE);
        poolableConnectionFactory.setDefaultAutoCommit(Boolean.TRUE);

        GenericObjectPool<PoolableConnection> connectionPool =
                new GenericObjectPool<>(poolableConnectionFactory, config);
        poolableConnectionFactory.setPool(connectionPool);
        PoolingDataSource<PoolableConnection> dataSource =
                new PoolingDataSource<>(connectionPool);

        ConnectionThread[] connectionThreads = new ConnectionThread[10];
        Thread[] threads = new Thread[10];

        for (int i = 0; i < 10; i++) {
            connectionThreads[i] = new ConnectionThread(dataSource);
            threads[i] = new Thread(connectionThreads[i]);
        }
        for (int i = 0; i < 10; i++) {
            threads[i].start();
        }
        for (int i = 0; i < 10; i++) {
            while (threads[i].isAlive()){//JDK1.5: getState() != Thread.State.TERMINATED) {
                Thread.sleep(100);
            }
            if (!connectionThreads[i].getResult()) {
                fail("Exception during getConnection");
            }
        }
    }

    private static final class ConnectionThread implements Runnable {
        private final DataSource ds;
        private volatile boolean result = true;

        private ConnectionThread(DataSource ds) {
            this.ds = ds;
        }

        @Override
        public void run() {
            Connection conn = null;
            try {
                conn = ds.getConnection();
            } catch (Exception e) {
                e.printStackTrace();
                result = false;
            } finally {
                if (conn != null) {
                    try {
                        conn.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                        result = false;
                    }
                }
            }
        }

        public boolean getResult() {
            return result;
        }
    }

}

@@ -897,16 +897,45 @@
 nection;
+%0Aimport java.util.Properties;
 %0A%0Aimport
@@ -1407,16 +1407,30 @@
 agerInit
+WithProperties
 () throw
@@ -1455,232 +1455,745 @@
     
-System.setProperty(%22jdbc.drivers%22,%0A                %22org.apache.commons.dbcp2.TesterDriver%22);%0A        GenericObjectPoolConfig config = new GenericObjectPoolConfig();%0A        config.setMaxTotal(10);%0A        config.setMaxIdle(0
+testDriverManagerInit(true);%0A    %7D%0A%0A    @Test%0A    public void testDriverManagerInitWithCredentials() throws Exception %7B%0A        testDriverManagerInit(false);%0A    %7D%0A%0A    public void testDriverManagerInit(final boolean withProperties) throws Exception %7B%0A        System.setProperty(%22jdbc.drivers%22,%0A                %22org.apache.commons.dbcp2.TesterDriver%22);%0A        GenericObjectPoolConfig config = new GenericObjectPoolConfig();%0A        config.setMaxTotal(10);%0A        config.setMaxIdle(0);%0A        Properties properties = new Properties();%0A        // The names %22user%22 and %22password%22 are specified in java.sql.DriverManager.getConnection(String, String, String)%0A        properties.put(%22user%22, %22foo%22);%0A        properties.put(%22password%22, %22bar%22
 );%0A 
@@ -2234,33 +2234,55 @@
 nectionFactory =
-%0A
+ withProperties ? %0A    
             new 
@@ -2312,37 +2312,116 @@
 Factory(
-%0A                    
+%22jdbc:apache:commons:testdriver%22, properties) : %0A                new DriverManagerConnectionFactory(
 %22jdbc:ap
@@ -2445,36 +2445,16 @@
 driver%22,
-%0A                   
  %22foo%22, 
@@ -3712,17 +3712,44 @@
 nnection
-%22
+(): %22 + connectionThreads%5Bi%5D
 );%0A     
@@ -4648,26 +4648,168 @@
 esult;%0A        %7D
+%0A%0A        @Override%0A        public String toString() %7B%0A            return %22ConnectionThread %5Bds=%22 + ds + %22, result=%22 + result + %22%5D%22;%0A        %7D
 %0A    %7D%0A%0A%7D%0A

Add test Properties ctor.