View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.dbcp2;
19  
20  import static org.junit.jupiter.api.Assertions.assertThrows;
21  import static org.junit.jupiter.api.Assertions.fail;
22  
23  import java.sql.Connection;
24  import java.sql.SQLException;
25  import java.util.Properties;
26  
27  import javax.sql.DataSource;
28  
29  import org.apache.commons.pool2.impl.GenericObjectPool;
30  import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
31  import org.junit.jupiter.api.AfterAll;
32  import org.junit.jupiter.api.BeforeAll;
33  import org.junit.jupiter.api.Test;
34  
35  /**
36   * This test *must* execute before all other tests to be effective as it tests
37   * the initialization of DriverManager.
38   * Based on the test case for DBCP-212 written by Marcos Sanz
39   */
40  public class TestDriverManagerConnectionFactory {
41  
42      private static final class ConnectionThread implements Runnable {
43          private final DataSource ds;
44          private volatile boolean result = true;
45  
46          private ConnectionThread(final DataSource ds) {
47              this.ds = ds;
48          }
49  
50          public boolean getResult() {
51              return result;
52          }
53  
54          @Override
55          public void run() {
56              Connection conn = null;
57              try {
58                  conn = ds.getConnection();
59              } catch (final Exception e) {
60                  e.printStackTrace();
61                  result = false;
62              } finally {
63                  if (conn != null) {
64                      try {
65                          conn.close();
66                      } catch (final Exception e) {
67                          e.printStackTrace();
68                          result = false;
69                      }
70                  }
71              }
72          }
73  
74          @Override
75          public String toString() {
76              return "ConnectionThread [ds=" + ds + ", result=" + result + "]";
77          }
78      }
79  
80      private static final String KEY_JDBC_DRIVERS = "jdbc.drivers";
81  
82      @AfterAll
83      public static void afterClass() {
84          System.clearProperty(KEY_JDBC_DRIVERS);
85      }
86  
87      @BeforeAll
88      public static void beforeClass() {
89          System.setProperty(KEY_JDBC_DRIVERS, "org.apache.commons.dbcp2.TesterDriver");
90      }
91  
92      @Test
93      public void testDriverManagerCredentialsInUrl() throws SQLException {
94          final DriverManagerConnectionFactory cf = new DriverManagerConnectionFactory("jdbc:apache:commons:testdriver;user=foo;password=bar", null,  (char[]) null);
95          cf.createConnection();
96      }
97  
98      public void testDriverManagerInit(final boolean withProperties) throws Exception {
99          final GenericObjectPoolConfig<PoolableConnection> config = new GenericObjectPoolConfig<>();
100         config.setMaxTotal(10);
101         config.setMaxIdle(0);
102         final Properties properties = new Properties();
103         // The names "user" and "password" are specified in java.sql.DriverManager.getConnection(String, String, String)
104         properties.setProperty(Constants.KEY_USER, "foo");
105         properties.setProperty(Constants.KEY_PASSWORD, "bar");
106         final ConnectionFactory connectionFactory = withProperties ?
107                 new DriverManagerConnectionFactory("jdbc:apache:commons:testdriver", properties) :
108                 new DriverManagerConnectionFactory("jdbc:apache:commons:testdriver", "foo", "bar");
109         final PoolableConnectionFactory poolableConnectionFactory =
110             new PoolableConnectionFactory(connectionFactory, null);
111         poolableConnectionFactory.setDefaultReadOnly(Boolean.FALSE);
112         poolableConnectionFactory.setDefaultAutoCommit(Boolean.TRUE);
113 
114         final GenericObjectPool<PoolableConnection> connectionPool =
115                 new GenericObjectPool<>(poolableConnectionFactory, config);
116         poolableConnectionFactory.setPool(connectionPool);
117         final PoolingDataSource<PoolableConnection> dataSource =
118                 new PoolingDataSource<>(connectionPool);
119 
120         final ConnectionThread[] connectionThreads = new ConnectionThread[10];
121         final Thread[] threads = new Thread[10];
122 
123         for (int i = 0; i < 10; i++) {
124             connectionThreads[i] = new ConnectionThread(dataSource);
125             threads[i] = new Thread(connectionThreads[i]);
126         }
127         for (int i = 0; i < 10; i++) {
128             threads[i].start();
129         }
130         for (int i = 0; i < 10; i++) {
131             while (threads[i].isAlive()){//JDK1.5: getState() != Thread.State.TERMINATED) {
132                 Thread.sleep(100);
133             }
134             if (!connectionThreads[i].getResult()) {
135                 fail("Exception during getConnection(): " + connectionThreads[i]);
136             }
137         }
138     }
139 
140     @Test
141     public void testDriverManagerInitWithCredentials() throws Exception {
142         testDriverManagerInit(false);
143     }
144 
145     @Test
146     public void testDriverManagerInitWithEmptyProperties() throws Exception {
147         final ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(
148                 "jdbc:apache:commons:testdriver;user=foo;password=bar");
149         connectionFactory.createConnection();
150     }
151 
152     @Test
153     public void testDriverManagerInitWithProperties() throws Exception {
154         testDriverManagerInit(true);
155     }
156 
157     @Test
158     public void testDriverManagerWithoutCredentials() {
159         final DriverManagerConnectionFactory cf = new DriverManagerConnectionFactory("jdbc:apache:commons:testdriver", null,  (char[]) null);
160         assertThrows(ArrayIndexOutOfBoundsException.class, cf::createConnection); // thrown by TestDriver due to missing user
161     }
162 
163     @Test
164     public void testDriverManagerWithoutPassword() {
165         final DriverManagerConnectionFactory cf = new DriverManagerConnectionFactory("jdbc:apache:commons:testdriver", "user", (char[]) null);
166         assertThrows(SQLException.class, cf::createConnection); // thrown by TestDriver due to invalid password
167     }
168 
169     @Test
170     public void testDriverManagerWithoutUser() {
171         final DriverManagerConnectionFactory cf = new DriverManagerConnectionFactory("jdbc:apache:commons:testdriver", null, "pass");
172         assertThrows(IndexOutOfBoundsException.class, cf::createConnection); // thrown by TestDriver due to missing user
173     }
174 
175 }