• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mybatis / ibatis-2 / 753

05 Jan 2026 01:30AM UTC coverage: 65.569% (+0.03%) from 65.537%
753

push

github

web-flow
Merge pull request #346 from hazendaz/master

Minor code cleanups

1598 of 2797 branches covered (57.13%)

19 of 30 new or added lines in 9 files covered. (63.33%)

1 existing line in 1 file now uncovered.

5020 of 7656 relevant lines covered (65.57%)

0.66 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

42.82
/src/main/java/com/ibatis/common/jdbc/SimpleDataSource.java
1
/*
2
 * Copyright 2004-2026 the original author or authors.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *    https://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package com.ibatis.common.jdbc;
17

18
import com.ibatis.common.beans.ClassInfo;
19
import com.ibatis.common.logging.Log;
20
import com.ibatis.common.logging.LogFactory;
21
import com.ibatis.common.resources.Resources;
22

23
import java.io.PrintWriter;
24
import java.lang.reflect.InvocationHandler;
25
import java.lang.reflect.Method;
26
import java.lang.reflect.Proxy;
27
import java.sql.CallableStatement;
28
import java.sql.Connection;
29
import java.sql.DatabaseMetaData;
30
import java.sql.DriverManager;
31
import java.sql.PreparedStatement;
32
import java.sql.ResultSet;
33
import java.sql.SQLException;
34
import java.sql.SQLFeatureNotSupportedException;
35
import java.sql.SQLWarning;
36
import java.sql.Savepoint;
37
import java.sql.Statement;
38
import java.util.ArrayList;
39
import java.util.Iterator;
40
import java.util.List;
41
import java.util.Map;
42
import java.util.Properties;
43
import java.util.logging.Logger;
44

45
import javax.sql.DataSource;
46

47
/**
48
 * This is a simple, synchronous, thread-safe database connection pool.
49
 * <p>
50
 * REQUIRED PROPERTIES ------------------- JDBC.Driver JDBC.ConnectionURL JDBC.Username JDBC.Password
51
 * <p>
52
 * Pool.MaximumActiveConnections Pool.MaximumIdleConnections Pool.MaximumCheckoutTime Pool.TimeToWait Pool.PingQuery
53
 * Pool.PingEnabled Pool.PingConnectionsOlderThan Pool.PingConnectionsNotUsedFor Pool.QuietMode
54
 */
55
public class SimpleDataSource implements DataSource {
56

57
  /** The Constant log. */
58
  private static final Log log = LogFactory.getLog(SimpleDataSource.class);
1✔
59

60
  /** The Constant PROP_JDBC_DRIVER. */
61
  // Required Properties
62
  private static final String PROP_JDBC_DRIVER = "JDBC.Driver";
63

64
  /** The Constant PROP_JDBC_URL. */
65
  private static final String PROP_JDBC_URL = "JDBC.ConnectionURL";
66

67
  /** The Constant PROP_JDBC_USERNAME. */
68
  private static final String PROP_JDBC_USERNAME = "JDBC.Username";
69

70
  /** The Constant PROP_JDBC_PASSWORD. */
71
  private static final String PROP_JDBC_PASSWORD = "JDBC.Password";
72

73
  /** The Constant PROP_JDBC_DEFAULT_AUTOCOMMIT. */
74
  private static final String PROP_JDBC_DEFAULT_AUTOCOMMIT = "JDBC.DefaultAutoCommit";
75

76
  /** The Constant PROP_POOL_MAX_ACTIVE_CONN. */
77
  // Optional Properties
78
  private static final String PROP_POOL_MAX_ACTIVE_CONN = "Pool.MaximumActiveConnections";
79

80
  /** The Constant PROP_POOL_MAX_IDLE_CONN. */
81
  private static final String PROP_POOL_MAX_IDLE_CONN = "Pool.MaximumIdleConnections";
82

83
  /** The Constant PROP_POOL_MAX_CHECKOUT_TIME. */
84
  private static final String PROP_POOL_MAX_CHECKOUT_TIME = "Pool.MaximumCheckoutTime";
85

86
  /** The Constant PROP_POOL_TIME_TO_WAIT. */
87
  private static final String PROP_POOL_TIME_TO_WAIT = "Pool.TimeToWait";
88

89
  /** The Constant PROP_POOL_PING_QUERY. */
90
  private static final String PROP_POOL_PING_QUERY = "Pool.PingQuery";
91

92
  /** The Constant PROP_POOL_PING_CONN_OLDER_THAN. */
93
  private static final String PROP_POOL_PING_CONN_OLDER_THAN = "Pool.PingConnectionsOlderThan";
94

95
  /** The Constant PROP_POOL_PING_ENABLED. */
96
  private static final String PROP_POOL_PING_ENABLED = "Pool.PingEnabled";
97

98
  /** The Constant PROP_POOL_PING_CONN_NOT_USED_FOR. */
99
  private static final String PROP_POOL_PING_CONN_NOT_USED_FOR = "Pool.PingConnectionsNotUsedFor";
100

101
  /** The expected connection type code. */
102
  private int expectedConnectionTypeCode;
103

104
  /** The Constant ADD_DRIVER_PROPS_PREFIX. */
105
  // Additional Driver Properties prefix
106
  private static final String ADD_DRIVER_PROPS_PREFIX = "Driver.";
107

108
  /** The Constant ADD_DRIVER_PROPS_PREFIX_LENGTH. */
109
  private static final int ADD_DRIVER_PROPS_PREFIX_LENGTH = ADD_DRIVER_PROPS_PREFIX.length();
1✔
110

111
  /** The pool lock. */
112
  // ----- BEGIN: FIELDS LOCKED BY POOL_LOCK -----
113
  private final Object POOL_LOCK = new Object();
1✔
114

115
  /** The idle connections. */
116
  private List idleConnections = new ArrayList<>();
1✔
117

118
  /** The active connections. */
119
  private List activeConnections = new ArrayList<>();
1✔
120

121
  /** The request count. */
122
  private long requestCount = 0;
1✔
123

124
  /** The accumulated request time. */
125
  private long accumulatedRequestTime = 0;
1✔
126

127
  /** The accumulated checkout time. */
128
  private long accumulatedCheckoutTime = 0;
1✔
129

130
  /** The claimed overdue connection count. */
131
  private long claimedOverdueConnectionCount = 0;
1✔
132

133
  /** The accumulated checkout time of overdue connections. */
134
  private long accumulatedCheckoutTimeOfOverdueConnections = 0;
1✔
135

136
  /** The accumulated wait time. */
137
  private long accumulatedWaitTime = 0;
1✔
138

139
  /** The had to wait count. */
140
  private long hadToWaitCount = 0;
1✔
141

142
  /** The bad connection count. */
143
  private long badConnectionCount = 0;
1✔
144
  // ----- END: FIELDS LOCKED BY POOL_LOCK -----
145

146
  /** The jdbc driver. */
147
  // ----- BEGIN: PROPERTY FIELDS FOR CONFIGURATION -----
148
  private String jdbcDriver;
149

150
  /** The jdbc url. */
151
  private String jdbcUrl;
152

153
  /** The jdbc username. */
154
  private String jdbcUsername;
155

156
  /** The jdbc password. */
157
  private String jdbcPassword;
158

159
  /** The jdbc default auto commit. */
160
  private boolean jdbcDefaultAutoCommit;
161

162
  /** The driver props. */
163
  private Properties driverProps;
164

165
  /** The use driver props. */
166
  private boolean useDriverProps;
167

168
  /** The pool maximum active connections. */
169
  private int poolMaximumActiveConnections;
170

171
  /** The pool maximum idle connections. */
172
  private int poolMaximumIdleConnections;
173

174
  /** The pool maximum checkout time. */
175
  private int poolMaximumCheckoutTime;
176

177
  /** The pool time to wait. */
178
  private int poolTimeToWait;
179

180
  /** The pool ping query. */
181
  private String poolPingQuery;
182

183
  /** The pool ping enabled. */
184
  private boolean poolPingEnabled;
185

186
  /** The pool ping connections older than. */
187
  private int poolPingConnectionsOlderThan;
188

189
  /** The pool ping connections not used for. */
190
  private int poolPingConnectionsNotUsedFor;
191

192
  // ----- END: PROPERTY FIELDS FOR CONFIGURATION -----
193

194
  /**
195
   * Constructor to allow passing in a map of properties for configuration.
196
   *
197
   * @param props
198
   *          - the configuration parameters
199
   */
200
  public SimpleDataSource(Map props) {
1✔
201
    initialize(props);
1✔
202
  }
1✔
203

204
  /**
205
   * Initialize.
206
   *
207
   * @param props
208
   *          the props
209
   */
210
  private void initialize(Map props) {
211
    try {
212
      String prop_pool_ping_query = null;
1✔
213

214
      if (props == null) {
1!
215
        throw new RuntimeException("SimpleDataSource: The properties map passed to the initializer was null.");
×
216
      }
217

218
      if (!props.containsKey(PROP_JDBC_DRIVER) || !props.containsKey(PROP_JDBC_URL)
1!
219
          || !props.containsKey(PROP_JDBC_USERNAME) || !props.containsKey(PROP_JDBC_PASSWORD)) {
1!
UNCOV
220
        throw new RuntimeException("SimpleDataSource: Some properties were not set.");
×
221
      }
222
      jdbcDriver = (String) props.get(PROP_JDBC_DRIVER);
1✔
223
      jdbcUrl = (String) props.get(PROP_JDBC_URL);
1✔
224
      jdbcUsername = (String) props.get(PROP_JDBC_USERNAME);
1✔
225
      jdbcPassword = (String) props.get(PROP_JDBC_PASSWORD);
1✔
226

227
      poolMaximumActiveConnections = props.containsKey(PROP_POOL_MAX_ACTIVE_CONN)
1✔
228
          ? Integer.parseInt((String) props.get(PROP_POOL_MAX_ACTIVE_CONN)) : 10;
1✔
229

230
      poolMaximumIdleConnections = props.containsKey(PROP_POOL_MAX_IDLE_CONN)
1✔
231
          ? Integer.parseInt((String) props.get(PROP_POOL_MAX_IDLE_CONN)) : 5;
1✔
232

233
      poolMaximumCheckoutTime = props.containsKey(PROP_POOL_MAX_CHECKOUT_TIME)
1✔
234
          ? Integer.parseInt((String) props.get(PROP_POOL_MAX_CHECKOUT_TIME)) : 20000;
1✔
235

236
      poolTimeToWait = props.containsKey(PROP_POOL_TIME_TO_WAIT)
1✔
237
          ? Integer.parseInt((String) props.get(PROP_POOL_TIME_TO_WAIT)) : 20000;
1✔
238

239
      poolPingEnabled = props.containsKey(PROP_POOL_PING_ENABLED)
1✔
240
          && Boolean.parseBoolean((String) props.get(PROP_POOL_PING_ENABLED));
1!
241

242
      prop_pool_ping_query = (String) props.get(PROP_POOL_PING_QUERY);
1✔
243
      poolPingQuery = props.containsKey(PROP_POOL_PING_QUERY) ? prop_pool_ping_query : "NO PING QUERY SET";
1✔
244

245
      poolPingConnectionsOlderThan = props.containsKey(PROP_POOL_PING_CONN_OLDER_THAN)
1✔
246
          ? Integer.parseInt((String) props.get(PROP_POOL_PING_CONN_OLDER_THAN)) : 0;
1✔
247

248
      poolPingConnectionsNotUsedFor = props.containsKey(PROP_POOL_PING_CONN_NOT_USED_FOR)
1✔
249
          ? Integer.parseInt((String) props.get(PROP_POOL_PING_CONN_NOT_USED_FOR)) : 0;
1✔
250

251
      jdbcDefaultAutoCommit = props.containsKey(PROP_JDBC_DEFAULT_AUTOCOMMIT)
1✔
252
          && Boolean.parseBoolean((String) props.get(PROP_JDBC_DEFAULT_AUTOCOMMIT));
1!
253

254
      useDriverProps = false;
1✔
255
      Iterator propIter = props.keySet().iterator();
1✔
256
      driverProps = new Properties();
1✔
257
      driverProps.put("user", jdbcUsername);
1✔
258
      driverProps.put("password", jdbcPassword);
1✔
259
      while (propIter.hasNext()) {
1✔
260
        String name = (String) propIter.next();
1✔
261
        String value = (String) props.get(name);
1✔
262
        if (name.startsWith(ADD_DRIVER_PROPS_PREFIX)) {
1!
263
          driverProps.put(name.substring(ADD_DRIVER_PROPS_PREFIX_LENGTH), value);
×
264
          useDriverProps = true;
×
265
        }
266
      }
1✔
267

268
      expectedConnectionTypeCode = assembleConnectionTypeCode(jdbcUrl, jdbcUsername, jdbcPassword);
1✔
269

270
      Resources.instantiate(jdbcDriver);
1✔
271

272
      if (poolPingEnabled && (!props.containsKey(PROP_POOL_PING_QUERY) || prop_pool_ping_query.trim().length() == 0)) {
1!
273
        throw new RuntimeException("SimpleDataSource: property '" + PROP_POOL_PING_ENABLED + "' is true, but property '"
×
274
            + PROP_POOL_PING_QUERY + "' is not set correctly.");
275
      }
276

277
    } catch (Exception e) {
×
278
      log.error("SimpleDataSource: Error while loading properties. Cause: " + e.toString(), e);
×
279
      throw new RuntimeException("SimpleDataSource: Error while loading properties. Cause: " + e, e);
×
280
    }
1✔
281
  }
1✔
282

283
  /**
284
   * Assemble connection type code.
285
   *
286
   * @param url
287
   *          the url
288
   * @param username
289
   *          the username
290
   * @param password
291
   *          the password
292
   *
293
   * @return the int
294
   */
295
  private int assembleConnectionTypeCode(String url, String username, String password) {
296
    return ("" + url + username + password).hashCode();
1✔
297
  }
298

299
  /**
300
   * @see javax.sql.DataSource#getConnection()
301
   */
302
  @Override
303
  public Connection getConnection() throws SQLException {
304
    return popConnection(jdbcUsername, jdbcPassword).getProxyConnection();
1✔
305
  }
306

307
  /**
308
   * @see javax.sql.DataSource#getConnection(java.lang.String, java.lang.String)
309
   */
310
  @Override
311
  public Connection getConnection(String username, String password) throws SQLException {
312
    return popConnection(username, password).getProxyConnection();
×
313
  }
314

315
  /**
316
   * @see javax.sql.DataSource#setLoginTimeout(int)
317
   */
318
  @Override
319
  public void setLoginTimeout(int loginTimeout) throws SQLException {
320
    DriverManager.setLoginTimeout(loginTimeout);
×
321
  }
×
322

323
  /**
324
   * @see javax.sql.DataSource#getLoginTimeout()
325
   */
326
  @Override
327
  public int getLoginTimeout() throws SQLException {
328
    return DriverManager.getLoginTimeout();
×
329
  }
330

331
  /**
332
   * @see javax.sql.DataSource#setLogWriter(java.io.PrintWriter)
333
   */
334
  @Override
335
  public void setLogWriter(PrintWriter logWriter) throws SQLException {
336
    DriverManager.setLogWriter(logWriter);
×
337
  }
×
338

339
  /**
340
   * @see javax.sql.DataSource#getLogWriter()
341
   */
342
  @Override
343
  public PrintWriter getLogWriter() throws SQLException {
344
    return DriverManager.getLogWriter();
×
345
  }
346

347
  /**
348
   * If a connection has not been used in this many milliseconds, ping the database to make sure the connection is still
349
   * good.
350
   *
351
   * @return the number of milliseconds of inactivity that will trigger a ping
352
   */
353
  public int getPoolPingConnectionsNotUsedFor() {
354
    return poolPingConnectionsNotUsedFor;
×
355
  }
356

357
  /**
358
   * Getter for the name of the JDBC driver class used.
359
   *
360
   * @return The name of the class
361
   */
362
  public String getJdbcDriver() {
363
    return jdbcDriver;
×
364
  }
365

366
  /**
367
   * Getter of the JDBC URL used.
368
   *
369
   * @return The JDBC URL
370
   */
371
  public String getJdbcUrl() {
372
    return jdbcUrl;
×
373
  }
374

375
  /**
376
   * Getter for the JDBC user name used.
377
   *
378
   * @return The user name
379
   */
380
  public String getJdbcUsername() {
381
    return jdbcUsername;
×
382
  }
383

384
  /**
385
   * Getter for the JDBC password used.
386
   *
387
   * @return The password
388
   */
389
  public String getJdbcPassword() {
390
    return jdbcPassword;
×
391
  }
392

393
  /**
394
   * Getter for the maximum number of active connections.
395
   *
396
   * @return The maximum number of active connections
397
   */
398
  public int getPoolMaximumActiveConnections() {
399
    return poolMaximumActiveConnections;
×
400
  }
401

402
  /**
403
   * Getter for the maximum number of idle connections.
404
   *
405
   * @return The maximum number of idle connections
406
   */
407
  public int getPoolMaximumIdleConnections() {
408
    return poolMaximumIdleConnections;
×
409
  }
410

411
  /**
412
   * Getter for the maximum time a connection can be used before it *may* be given away again.
413
   *
414
   * @return The maximum time
415
   */
416
  public int getPoolMaximumCheckoutTime() {
417
    return poolMaximumCheckoutTime;
×
418
  }
419

420
  /**
421
   * Getter for the time to wait before retrying to get a connection.
422
   *
423
   * @return The time to wait
424
   */
425
  public int getPoolTimeToWait() {
426
    return poolTimeToWait;
×
427
  }
428

429
  /**
430
   * Getter for the query to be used to check a connection.
431
   *
432
   * @return The query
433
   */
434
  public String getPoolPingQuery() {
435
    return poolPingQuery;
×
436
  }
437

438
  /**
439
   * Getter to tell if we should use the ping query.
440
   *
441
   * @return True if we need to check a connection before using it
442
   */
443
  public boolean isPoolPingEnabled() {
444
    return poolPingEnabled;
×
445
  }
446

447
  /**
448
   * Getter for the age of connections that should be pinged before using.
449
   *
450
   * @return The age
451
   */
452
  public int getPoolPingConnectionsOlderThan() {
453
    return poolPingConnectionsOlderThan;
×
454
  }
455

456
  /**
457
   * Gets the expected connection type code.
458
   *
459
   * @return the expected connection type code
460
   */
461
  private int getExpectedConnectionTypeCode() {
462
    return expectedConnectionTypeCode;
1✔
463
  }
464

465
  /**
466
   * Getter for the number of connection requests made.
467
   *
468
   * @return The number of connection requests made
469
   */
470
  public long getRequestCount() {
471
    synchronized (POOL_LOCK) {
×
472
      return requestCount;
×
473
    }
474
  }
475

476
  /**
477
   * Getter for the average time required to get a connection to the database.
478
   *
479
   * @return The average time
480
   */
481
  public long getAverageRequestTime() {
482
    synchronized (POOL_LOCK) {
×
483
      return requestCount == 0 ? 0 : accumulatedRequestTime / requestCount;
×
484
    }
485
  }
486

487
  /**
488
   * Getter for the average time spent waiting for connections that were in use.
489
   *
490
   * @return The average time
491
   */
492
  public long getAverageWaitTime() {
493
    synchronized (POOL_LOCK) {
×
494
      return hadToWaitCount == 0 ? 0 : accumulatedWaitTime / hadToWaitCount;
×
495
    }
496
  }
497

498
  /**
499
   * Getter for the number of requests that had to wait for connections that were in use.
500
   *
501
   * @return The number of requests that had to wait
502
   */
503
  public long getHadToWaitCount() {
504
    synchronized (POOL_LOCK) {
×
505
      return hadToWaitCount;
×
506
    }
507
  }
508

509
  /**
510
   * Getter for the number of invalid connections that were found in the pool.
511
   *
512
   * @return The number of invalid connections
513
   */
514
  public long getBadConnectionCount() {
515
    synchronized (POOL_LOCK) {
×
516
      return badConnectionCount;
×
517
    }
518
  }
519

520
  /**
521
   * Getter for the number of connections that were claimed before they were returned.
522
   *
523
   * @return The number of connections
524
   */
525
  public long getClaimedOverdueConnectionCount() {
526
    synchronized (POOL_LOCK) {
×
527
      return claimedOverdueConnectionCount;
×
528
    }
529
  }
530

531
  /**
532
   * Getter for the average age of overdue connections.
533
   *
534
   * @return The average age
535
   */
536
  public long getAverageOverdueCheckoutTime() {
537
    synchronized (POOL_LOCK) {
×
538
      return claimedOverdueConnectionCount == 0 ? 0
×
539
          : accumulatedCheckoutTimeOfOverdueConnections / claimedOverdueConnectionCount;
×
540
    }
541
  }
542

543
  /**
544
   * Getter for the average age of a connection checkout.
545
   *
546
   * @return The average age
547
   */
548
  public long getAverageCheckoutTime() {
549
    synchronized (POOL_LOCK) {
×
550
      return requestCount == 0 ? 0 : accumulatedCheckoutTime / requestCount;
×
551
    }
552
  }
553

554
  /**
555
   * Returns the status of the connection pool.
556
   *
557
   * @return The status
558
   */
559
  public String getStatus() {
560
    StringBuilder builder = new StringBuilder();
×
561

562
    builder.append("\n===============================================================");
×
563
    builder.append("\n jdbcDriver                     ").append(jdbcDriver);
×
564
    builder.append("\n jdbcUrl                        ").append(jdbcUrl);
×
565
    builder.append("\n jdbcUsername                   ").append(jdbcUsername);
×
566
    builder.append("\n jdbcPassword                   ").append(jdbcPassword == null ? "NULL" : "************");
×
567
    builder.append("\n poolMaxActiveConnections       ").append(poolMaximumActiveConnections);
×
568
    builder.append("\n poolMaxIdleConnections         ").append(poolMaximumIdleConnections);
×
569
    builder.append("\n poolMaxCheckoutTime            " + poolMaximumCheckoutTime);
×
570
    builder.append("\n poolTimeToWait                 " + poolTimeToWait);
×
571
    builder.append("\n poolPingEnabled                " + poolPingEnabled);
×
572
    builder.append("\n poolPingQuery                  " + poolPingQuery);
×
573
    builder.append("\n poolPingConnectionsOlderThan   " + poolPingConnectionsOlderThan);
×
574
    builder.append("\n poolPingConnectionsNotUsedFor  " + poolPingConnectionsNotUsedFor);
×
575
    builder.append("\n --------------------------------------------------------------");
×
576
    builder.append("\n activeConnections              " + activeConnections.size());
×
577
    builder.append("\n idleConnections                " + idleConnections.size());
×
578
    builder.append("\n requestCount                   " + getRequestCount());
×
579
    builder.append("\n averageRequestTime             " + getAverageRequestTime());
×
580
    builder.append("\n averageCheckoutTime            " + getAverageCheckoutTime());
×
581
    builder.append("\n claimedOverdue                 " + getClaimedOverdueConnectionCount());
×
582
    builder.append("\n averageOverdueCheckoutTime     " + getAverageOverdueCheckoutTime());
×
583
    builder.append("\n hadToWait                      " + getHadToWaitCount());
×
584
    builder.append("\n averageWaitTime                " + getAverageWaitTime());
×
585
    builder.append("\n badConnectionCount             " + getBadConnectionCount());
×
586
    builder.append("\n===============================================================");
×
587
    return builder.toString();
×
588
  }
589

590
  /**
591
   * Closes all of the connections in the pool.
592
   */
593
  public void forceCloseAll() {
594
    synchronized (POOL_LOCK) {
1✔
595
      for (int i = activeConnections.size(); i > 0; i--) {
1!
596
        try {
597
          SimplePooledConnection conn = (SimplePooledConnection) activeConnections.remove(i - 1);
×
598
          conn.invalidate();
×
599

600
          Connection realConn = conn.getRealConnection();
×
601
          if (!realConn.getAutoCommit()) {
×
602
            realConn.rollback();
×
603
          }
604
          realConn.close();
×
605
        } catch (Exception e) {
×
606
          // ignore
607
        }
×
608
      }
609
      for (int i = idleConnections.size(); i > 0; i--) {
1✔
610
        try {
611
          SimplePooledConnection conn = (SimplePooledConnection) idleConnections.remove(i - 1);
1✔
612
          conn.invalidate();
1✔
613

614
          Connection realConn = conn.getRealConnection();
1✔
615
          if (!realConn.getAutoCommit()) {
1✔
616
            realConn.rollback();
1✔
617
          }
618
          realConn.close();
1✔
619
        } catch (Exception e) {
×
620
          // ignore
621
        }
1✔
622
      }
623
    }
1✔
624
    if (log.isDebugEnabled()) {
1!
625
      log.debug("SimpleDataSource forcefully closed/removed all connections.");
×
626
    }
627
  }
1✔
628

629
  /**
630
   * Push connection.
631
   *
632
   * @param conn
633
   *          the conn
634
   *
635
   * @throws SQLException
636
   *           the SQL exception
637
   */
638
  private void pushConnection(SimplePooledConnection conn) throws SQLException {
639

640
    synchronized (POOL_LOCK) {
1✔
641
      activeConnections.remove(conn);
1✔
642
      if (conn.isValid()) {
1!
643
        if (idleConnections.size() < poolMaximumIdleConnections
1!
644
            && conn.getConnectionTypeCode() == getExpectedConnectionTypeCode()) {
1!
645
          accumulatedCheckoutTime += conn.getCheckoutTime();
1✔
646
          if (!conn.getRealConnection().getAutoCommit()) {
1✔
647
            conn.getRealConnection().rollback();
1✔
648
          }
649
          SimplePooledConnection newConn = new SimplePooledConnection(conn.getRealConnection(), this);
1✔
650
          idleConnections.add(newConn);
1✔
651
          newConn.setCreatedTimestamp(conn.getCreatedTimestamp());
1✔
652
          newConn.setLastUsedTimestamp(conn.getLastUsedTimestamp());
1✔
653
          conn.invalidate();
1✔
654
          if (log.isDebugEnabled()) {
1!
655
            log.debug("Returned connection " + newConn.getRealHashCode() + " to pool.");
×
656
          }
657
          POOL_LOCK.notifyAll();
1✔
658
        } else {
1✔
659
          accumulatedCheckoutTime += conn.getCheckoutTime();
×
660
          if (!conn.getRealConnection().getAutoCommit()) {
×
661
            conn.getRealConnection().rollback();
×
662
          }
663
          conn.getRealConnection().close();
×
664
          if (log.isDebugEnabled()) {
×
665
            log.debug("Closed connection " + conn.getRealHashCode() + ".");
×
666
          }
667
          conn.invalidate();
×
668
        }
669
      } else {
670
        if (log.isDebugEnabled()) {
×
671
          log.debug("A bad connection (" + conn.getRealHashCode()
×
672
              + ") attempted to return to the pool, discarding connection.");
673
        }
674
        badConnectionCount++;
×
675
      }
676
    }
1✔
677
  }
1✔
678

679
  /**
680
   * Pop connection.
681
   *
682
   * @param username
683
   *          the username
684
   * @param password
685
   *          the password
686
   *
687
   * @return the simple pooled connection
688
   *
689
   * @throws SQLException
690
   *           the SQL exception
691
   */
692
  private SimplePooledConnection popConnection(String username, String password) throws SQLException {
693
    boolean countedWait = false;
1✔
694
    SimplePooledConnection conn = null;
1✔
695
    long t = System.currentTimeMillis();
1✔
696
    int localBadConnectionCount = 0;
1✔
697

698
    while (conn == null) {
1✔
699
      synchronized (POOL_LOCK) {
1✔
700
        if (!idleConnections.isEmpty()) {
1✔
701
          // Pool has available connection
702
          conn = (SimplePooledConnection) idleConnections.remove(0);
1✔
703
          if (log.isDebugEnabled()) {
1!
704
            log.debug("Checked out connection " + conn.getRealHashCode() + " from pool.");
×
705
          }
706
        } else {
707
          // Pool does not have available connection
708
          if (activeConnections.size() < poolMaximumActiveConnections) {
1!
709
            // Can create new connection
710
            if (useDriverProps) {
1!
711
              conn = new SimplePooledConnection(DriverManager.getConnection(jdbcUrl, driverProps), this);
×
712
            } else {
713
              conn = new SimplePooledConnection(DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword), this);
1✔
714
            }
715
            Connection realConn = conn.getRealConnection();
1✔
716
            if (realConn.getAutoCommit() != jdbcDefaultAutoCommit) {
1✔
717
              realConn.setAutoCommit(jdbcDefaultAutoCommit);
1✔
718
            }
719
            if (log.isDebugEnabled()) {
1!
720
              log.debug("Created connection " + conn.getRealHashCode() + ".");
×
721
            }
722
          } else {
1✔
723
            // Cannot create new connection
724
            SimplePooledConnection oldestActiveConnection = (SimplePooledConnection) activeConnections.get(0);
×
725
            long longestCheckoutTime = oldestActiveConnection.getCheckoutTime();
×
726
            if (longestCheckoutTime > poolMaximumCheckoutTime) {
×
727
              // Can claim overdue connection
728
              claimedOverdueConnectionCount++;
×
729
              accumulatedCheckoutTimeOfOverdueConnections += longestCheckoutTime;
×
730
              accumulatedCheckoutTime += longestCheckoutTime;
×
731
              activeConnections.remove(oldestActiveConnection);
×
732
              if (!oldestActiveConnection.getRealConnection().getAutoCommit()) {
×
733
                oldestActiveConnection.getRealConnection().rollback();
×
734
              }
735
              conn = new SimplePooledConnection(oldestActiveConnection.getRealConnection(), this);
×
736
              oldestActiveConnection.invalidate();
×
737
              if (log.isDebugEnabled()) {
×
738
                log.debug("Claimed overdue connection " + conn.getRealHashCode() + ".");
×
739
              }
740
            } else {
741
              // Must wait
742
              try {
743
                if (!countedWait) {
×
744
                  hadToWaitCount++;
×
745
                  countedWait = true;
×
746
                }
747
                if (log.isDebugEnabled()) {
×
748
                  log.debug("Waiting as long as " + poolTimeToWait + " milliseconds for connection.");
×
749
                }
750
                long wt = System.currentTimeMillis();
×
751
                POOL_LOCK.wait(poolTimeToWait);
×
752
                accumulatedWaitTime += System.currentTimeMillis() - wt;
×
753
              } catch (InterruptedException e) {
×
754
                break;
×
755
              }
×
756
            }
757
          }
758
        }
759
        if (conn != null) {
1!
760
          if (conn.isValid()) {
1!
761
            if (!conn.getRealConnection().getAutoCommit()) {
1✔
762
              conn.getRealConnection().rollback();
1✔
763
            }
764
            conn.setConnectionTypeCode(assembleConnectionTypeCode(jdbcUrl, username, password));
1✔
765
            conn.setCheckoutTimestamp(System.currentTimeMillis());
1✔
766
            conn.setLastUsedTimestamp(System.currentTimeMillis());
1✔
767
            activeConnections.add(conn);
1✔
768
            requestCount++;
1✔
769
            accumulatedRequestTime += System.currentTimeMillis() - t;
1✔
770
          } else {
771
            if (log.isDebugEnabled()) {
×
772
              log.debug("A bad connection (" + conn.getRealHashCode()
×
773
                  + ") was returned from the pool, getting another connection.");
774
            }
775
            badConnectionCount++;
×
776
            localBadConnectionCount++;
×
777
            conn = null;
×
778
            if (localBadConnectionCount > poolMaximumIdleConnections + 3) {
×
779
              if (log.isDebugEnabled()) {
×
780
                log.debug("SimpleDataSource: Could not get a good connection to the database.");
×
781
              }
782
              throw new SQLException("SimpleDataSource: Could not get a good connection to the database.");
×
783
            }
784
          }
785
        }
786
      }
1✔
787

788
    }
789

790
    if (conn == null) {
1!
791
      if (log.isDebugEnabled()) {
×
792
        log.debug("SimpleDataSource: Unknown severe error condition.  The connection pool returned a null connection.");
×
793
      }
794
      throw new SQLException(
×
795
          "SimpleDataSource: Unknown severe error condition.  The connection pool returned a null connection.");
796
    }
797

798
    return conn;
1✔
799
  }
800

801
  /**
802
   * Method to check to see if a connection is still usable.
803
   *
804
   * @param conn
805
   *          - the connection to check
806
   *
807
   * @return True if the connection is still usable
808
   */
809
  private boolean pingConnection(SimplePooledConnection conn) {
810
    boolean result = true;
1✔
811

812
    try {
813
      result = !conn.getRealConnection().isClosed();
1!
814
    } catch (SQLException e) {
×
815
      if (log.isDebugEnabled()) {
×
816
        log.debug("Connection " + conn.getRealHashCode() + " is BAD: " + e.getMessage());
×
817
      }
818
      result = false;
×
819
    }
1✔
820

821
    if (result && poolPingEnabled) {
1!
822
      if (poolPingConnectionsOlderThan > 0 && conn.getAge() > poolPingConnectionsOlderThan
×
823
          || poolPingConnectionsNotUsedFor > 0 && conn.getTimeElapsedSinceLastUse() > poolPingConnectionsNotUsedFor) {
×
824

825
        try {
826
          if (log.isDebugEnabled()) {
×
827
            log.debug("Testing connection " + conn.getRealHashCode() + " ...");
×
828
          }
829
          Connection realConn = conn.getRealConnection();
×
830
          Statement statement = realConn.createStatement();
×
831
          ResultSet rs = statement.executeQuery(poolPingQuery);
×
832
          rs.close();
×
833
          statement.close();
×
834
          if (!realConn.getAutoCommit()) {
×
835
            realConn.rollback();
×
836
          }
837
          result = true;
×
838
          if (log.isDebugEnabled()) {
×
839
            log.debug("Connection " + conn.getRealHashCode() + " is GOOD!");
×
840
          }
841
        } catch (Exception e) {
×
842
          log.warn("Execution of ping query '" + poolPingQuery + "' failed: " + e.getMessage());
×
843
          try {
844
            conn.getRealConnection().close();
×
845
          } catch (Exception e2) {
×
846
            // ignore
847
          }
×
848
          result = false;
×
849
          if (log.isDebugEnabled()) {
×
850
            log.debug("Connection " + conn.getRealHashCode() + " is BAD: " + e.getMessage());
×
851
          }
852
        }
×
853
      }
854
    }
855
    return result;
1✔
856
  }
857

858
  /**
859
   * Unwraps a pooled connection to get to the 'real' connection.
860
   *
861
   * @param conn
862
   *          - the pooled connection to unwrap
863
   *
864
   * @return The 'real' connection
865
   */
866
  public static Connection unwrapConnection(Connection conn) {
867
    if (conn instanceof SimplePooledConnection) {
×
868
      return ((SimplePooledConnection) conn).getRealConnection();
×
869
    }
870
    return conn;
×
871
  }
872

873
  @Override
874
  protected void finalize() throws Throwable {
875
    forceCloseAll();
1✔
876
  }
1✔
877

878
  /**
879
   * --------------------------------------------------------------------------------------- SimplePooledConnection
880
   * ---------------------------------------------------------------------------------------.
881
   */
882
  public static class SimplePooledConnection implements InvocationHandler {
883

884
    /** The Constant CLOSE. */
885
    private static final String CLOSE = "close";
886

887
    /** The Constant IFACES. */
888
    private static final Class[] IFACES = { Connection.class };
1✔
889

890
    /** The hash code. */
891
    private int hashCode = 0;
1✔
892

893
    /** The data source. */
894
    private SimpleDataSource dataSource;
895

896
    /** The real connection. */
897
    private Connection realConnection;
898

899
    /** The proxy connection. */
900
    private Connection proxyConnection;
901

902
    /** The checkout timestamp. */
903
    private long checkoutTimestamp;
904

905
    /** The created timestamp. */
906
    private long createdTimestamp;
907

908
    /** The last used timestamp. */
909
    private long lastUsedTimestamp;
910

911
    /** The connection type code. */
912
    private int connectionTypeCode;
913

914
    /** The valid. */
915
    private boolean valid;
916

917
    /**
918
     * Constructor for SimplePooledConnection that uses the Connection and SimpleDataSource passed in.
919
     *
920
     * @param connection
921
     *          - the connection that is to be presented as a pooled connection
922
     * @param dataSource
923
     *          - the dataSource that the connection is from
924
     */
925
    public SimplePooledConnection(Connection connection, SimpleDataSource dataSource) {
1✔
926
      this.hashCode = connection.hashCode();
1✔
927
      this.realConnection = connection;
1✔
928
      this.dataSource = dataSource;
1✔
929
      this.createdTimestamp = System.currentTimeMillis();
1✔
930
      this.lastUsedTimestamp = System.currentTimeMillis();
1✔
931
      this.valid = true;
1✔
932

933
      proxyConnection = (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(), IFACES, this);
1✔
934
    }
1✔
935

936
    /**
937
     * Invalidates the connection.
938
     */
939
    public void invalidate() {
940
      valid = false;
1✔
941
    }
1✔
942

943
    /**
944
     * Method to see if the connection is usable.
945
     *
946
     * @return True if the connection is usable
947
     */
948
    public boolean isValid() {
949
      return valid && realConnection != null && dataSource.pingConnection(this);
1!
950
    }
951

952
    /**
953
     * Getter for the *real* connection that this wraps.
954
     *
955
     * @return The connection
956
     */
957
    public Connection getRealConnection() {
958
      return realConnection;
1✔
959
    }
960

961
    /**
962
     * Getter for the proxy for the connection.
963
     *
964
     * @return The proxy
965
     */
966
    public Connection getProxyConnection() {
967
      return proxyConnection;
1✔
968
    }
969

970
    /**
971
     * Gets the hashcode of the real connection (or 0 if it is null).
972
     *
973
     * @return The hashcode of the real connection (or 0 if it is null)
974
     */
975
    public int getRealHashCode() {
976
      if (realConnection == null) {
×
977
        return 0;
×
978
      }
979
      return realConnection.hashCode();
×
980
    }
981

982
    /**
983
     * Getter for the connection type (based on url + user + password).
984
     *
985
     * @return The connection type
986
     */
987
    public int getConnectionTypeCode() {
988
      return connectionTypeCode;
1✔
989
    }
990

991
    /**
992
     * Setter for the connection type.
993
     *
994
     * @param connectionTypeCode
995
     *          - the connection type
996
     */
997
    public void setConnectionTypeCode(int connectionTypeCode) {
998
      this.connectionTypeCode = connectionTypeCode;
1✔
999
    }
1✔
1000

1001
    /**
1002
     * Getter for the time that the connection was created.
1003
     *
1004
     * @return The creation timestamp
1005
     */
1006
    public long getCreatedTimestamp() {
1007
      return createdTimestamp;
1✔
1008
    }
1009

1010
    /**
1011
     * Setter for the time that the connection was created.
1012
     *
1013
     * @param createdTimestamp
1014
     *          - the timestamp
1015
     */
1016
    public void setCreatedTimestamp(long createdTimestamp) {
1017
      this.createdTimestamp = createdTimestamp;
1✔
1018
    }
1✔
1019

1020
    /**
1021
     * Getter for the time that the connection was last used.
1022
     *
1023
     * @return - the timestamp
1024
     */
1025
    public long getLastUsedTimestamp() {
1026
      return lastUsedTimestamp;
1✔
1027
    }
1028

1029
    /**
1030
     * Setter for the time that the connection was last used.
1031
     *
1032
     * @param lastUsedTimestamp
1033
     *          - the timestamp
1034
     */
1035
    public void setLastUsedTimestamp(long lastUsedTimestamp) {
1036
      this.lastUsedTimestamp = lastUsedTimestamp;
1✔
1037
    }
1✔
1038

1039
    /**
1040
     * Getter for the time since this connection was last used.
1041
     *
1042
     * @return - the time since the last use
1043
     */
1044
    public long getTimeElapsedSinceLastUse() {
1045
      return System.currentTimeMillis() - lastUsedTimestamp;
×
1046
    }
1047

1048
    /**
1049
     * Getter for the age of the connection.
1050
     *
1051
     * @return the age
1052
     */
1053
    public long getAge() {
1054
      return System.currentTimeMillis() - createdTimestamp;
×
1055
    }
1056

1057
    /**
1058
     * Getter for the timestamp that this connection was checked out.
1059
     *
1060
     * @return the timestamp
1061
     */
1062
    public long getCheckoutTimestamp() {
1063
      return checkoutTimestamp;
×
1064
    }
1065

1066
    /**
1067
     * Setter for the timestamp that this connection was checked out.
1068
     *
1069
     * @param timestamp
1070
     *          the timestamp
1071
     */
1072
    public void setCheckoutTimestamp(long timestamp) {
1073
      this.checkoutTimestamp = timestamp;
1✔
1074
    }
1✔
1075

1076
    /**
1077
     * Getter for the time that this connection has been checked out.
1078
     *
1079
     * @return the time
1080
     */
1081
    public long getCheckoutTime() {
1082
      return System.currentTimeMillis() - checkoutTimestamp;
1✔
1083
    }
1084

1085
    /**
1086
     * Gets the valid connection.
1087
     *
1088
     * @return the valid connection
1089
     */
1090
    private Connection getValidConnection() {
1091
      if (!valid) {
1!
1092
        throw new RuntimeException("Error accessing SimplePooledConnection. Connection is invalid.");
×
1093
      }
1094
      return realConnection;
1✔
1095
    }
1096

1097
    @Override
1098
    public int hashCode() {
1099
      return hashCode;
×
1100
    }
1101

1102
    /**
1103
     * Allows comparing this connection to another
1104
     *
1105
     * @param obj
1106
     *          - the other connection to test for equality
1107
     *
1108
     * @see java.lang.Object#equals(java.lang.Object)
1109
     */
1110
    @Override
1111
    public boolean equals(Object obj) {
1112
      if (obj instanceof SimplePooledConnection) {
1!
1113
        return realConnection.hashCode() == ((SimplePooledConnection) obj).realConnection.hashCode();
1✔
1114
      }
1115
      if (obj instanceof Connection) {
×
1116
        return hashCode == obj.hashCode();
×
1117
      }
1118
      return false;
×
1119
    }
1120

1121
    // **********************************
1122
    // Implemented Connection Methods -- Now handled by proxy
1123
    // **********************************
1124

1125
    /**
1126
     * Required for InvocationHandler implementation.
1127
     *
1128
     * @param proxy
1129
     *          - not used
1130
     * @param method
1131
     *          - the method to be executed
1132
     * @param args
1133
     *          - the parameters to be passed to the method
1134
     *
1135
     * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
1136
     */
1137
    @Override
1138
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
1139
      String methodName = method.getName();
1✔
1140
      if (CLOSE.hashCode() == methodName.hashCode() && CLOSE.equals(methodName)) {
1!
1141
        dataSource.pushConnection(this);
1✔
1142
        return null;
1✔
1143
      }
1144
      try {
1145
        return method.invoke(getValidConnection(), args);
1✔
1146
      } catch (Throwable t) {
1✔
1147
        throw ClassInfo.unwrapThrowable(t);
1✔
1148
      }
1149
    }
1150

1151
    /**
1152
     * Creates the statement.
1153
     *
1154
     * @return the statement
1155
     *
1156
     * @throws SQLException
1157
     *           the SQL exception
1158
     */
1159
    public Statement createStatement() throws SQLException {
1160
      return getValidConnection().createStatement();
×
1161
    }
1162

1163
    /**
1164
     * Prepare statement.
1165
     *
1166
     * @param sql
1167
     *          the sql
1168
     *
1169
     * @return the prepared statement
1170
     *
1171
     * @throws SQLException
1172
     *           the SQL exception
1173
     */
1174
    public PreparedStatement prepareStatement(String sql) throws SQLException {
1175
      return getValidConnection().prepareStatement(sql);
×
1176
    }
1177

1178
    /**
1179
     * Prepare call.
1180
     *
1181
     * @param sql
1182
     *          the sql
1183
     *
1184
     * @return the callable statement
1185
     *
1186
     * @throws SQLException
1187
     *           the SQL exception
1188
     */
1189
    public CallableStatement prepareCall(String sql) throws SQLException {
1190
      return getValidConnection().prepareCall(sql);
×
1191
    }
1192

1193
    /**
1194
     * Native SQL.
1195
     *
1196
     * @param sql
1197
     *          the sql
1198
     *
1199
     * @return the string
1200
     *
1201
     * @throws SQLException
1202
     *           the SQL exception
1203
     */
1204
    public String nativeSQL(String sql) throws SQLException {
1205
      return getValidConnection().nativeSQL(sql);
×
1206
    }
1207

1208
    /**
1209
     * Sets the auto commit.
1210
     *
1211
     * @param autoCommit
1212
     *          the new auto commit
1213
     *
1214
     * @throws SQLException
1215
     *           the SQL exception
1216
     */
1217
    public void setAutoCommit(boolean autoCommit) throws SQLException {
1218
      getValidConnection().setAutoCommit(autoCommit);
×
1219
    }
×
1220

1221
    /**
1222
     * Gets the auto commit.
1223
     *
1224
     * @return the auto commit
1225
     *
1226
     * @throws SQLException
1227
     *           the SQL exception
1228
     */
1229
    public boolean getAutoCommit() throws SQLException {
1230
      return getValidConnection().getAutoCommit();
×
1231
    }
1232

1233
    /**
1234
     * Commit.
1235
     *
1236
     * @throws SQLException
1237
     *           the SQL exception
1238
     */
1239
    public void commit() throws SQLException {
1240
      getValidConnection().commit();
×
1241
    }
×
1242

1243
    /**
1244
     * Rollback.
1245
     *
1246
     * @throws SQLException
1247
     *           the SQL exception
1248
     */
1249
    public void rollback() throws SQLException {
1250
      getValidConnection().rollback();
×
1251
    }
×
1252

1253
    /**
1254
     * Close.
1255
     *
1256
     * @throws SQLException
1257
     *           the SQL exception
1258
     */
1259
    public void close() throws SQLException {
1260
      dataSource.pushConnection(this);
×
1261
    }
×
1262

1263
    /**
1264
     * Checks if is closed.
1265
     *
1266
     * @return true, if is closed
1267
     *
1268
     * @throws SQLException
1269
     *           the SQL exception
1270
     */
1271
    public boolean isClosed() throws SQLException {
1272
      return getValidConnection().isClosed();
×
1273
    }
1274

1275
    /**
1276
     * Gets the meta data.
1277
     *
1278
     * @return the meta data
1279
     *
1280
     * @throws SQLException
1281
     *           the SQL exception
1282
     */
1283
    public DatabaseMetaData getMetaData() throws SQLException {
1284
      return getValidConnection().getMetaData();
×
1285
    }
1286

1287
    /**
1288
     * Sets the read only.
1289
     *
1290
     * @param readOnly
1291
     *          the new read only
1292
     *
1293
     * @throws SQLException
1294
     *           the SQL exception
1295
     */
1296
    public void setReadOnly(boolean readOnly) throws SQLException {
1297
      getValidConnection().setReadOnly(readOnly);
×
1298
    }
×
1299

1300
    /**
1301
     * Checks if is read only.
1302
     *
1303
     * @return true, if is read only
1304
     *
1305
     * @throws SQLException
1306
     *           the SQL exception
1307
     */
1308
    public boolean isReadOnly() throws SQLException {
1309
      return getValidConnection().isReadOnly();
×
1310
    }
1311

1312
    /**
1313
     * Sets the catalog.
1314
     *
1315
     * @param catalog
1316
     *          the new catalog
1317
     *
1318
     * @throws SQLException
1319
     *           the SQL exception
1320
     */
1321
    public void setCatalog(String catalog) throws SQLException {
1322
      getValidConnection().setCatalog(catalog);
×
1323
    }
×
1324

1325
    /**
1326
     * Gets the catalog.
1327
     *
1328
     * @return the catalog
1329
     *
1330
     * @throws SQLException
1331
     *           the SQL exception
1332
     */
1333
    public String getCatalog() throws SQLException {
1334
      return getValidConnection().getCatalog();
×
1335
    }
1336

1337
    /**
1338
     * Sets the transaction isolation.
1339
     *
1340
     * @param level
1341
     *          the new transaction isolation
1342
     *
1343
     * @throws SQLException
1344
     *           the SQL exception
1345
     */
1346
    public void setTransactionIsolation(int level) throws SQLException {
1347
      getValidConnection().setTransactionIsolation(level);
×
1348
    }
×
1349

1350
    /**
1351
     * Gets the transaction isolation.
1352
     *
1353
     * @return the transaction isolation
1354
     *
1355
     * @throws SQLException
1356
     *           the SQL exception
1357
     */
1358
    public int getTransactionIsolation() throws SQLException {
1359
      return getValidConnection().getTransactionIsolation();
×
1360
    }
1361

1362
    /**
1363
     * Gets the warnings.
1364
     *
1365
     * @return the warnings
1366
     *
1367
     * @throws SQLException
1368
     *           the SQL exception
1369
     */
1370
    public SQLWarning getWarnings() throws SQLException {
1371
      return getValidConnection().getWarnings();
×
1372
    }
1373

1374
    /**
1375
     * Clear warnings.
1376
     *
1377
     * @throws SQLException
1378
     *           the SQL exception
1379
     */
1380
    public void clearWarnings() throws SQLException {
1381
      getValidConnection().clearWarnings();
×
1382
    }
×
1383

1384
    /**
1385
     * Creates the statement.
1386
     *
1387
     * @param resultSetType
1388
     *          the result set type
1389
     * @param resultSetConcurrency
1390
     *          the result set concurrency
1391
     *
1392
     * @return the statement
1393
     *
1394
     * @throws SQLException
1395
     *           the SQL exception
1396
     */
1397
    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
1398
      return getValidConnection().createStatement(resultSetType, resultSetConcurrency);
×
1399
    }
1400

1401
    /**
1402
     * Prepare statement.
1403
     *
1404
     * @param sql
1405
     *          the sql
1406
     * @param resultSetType
1407
     *          the result set type
1408
     * @param resultSetConcurrency
1409
     *          the result set concurrency
1410
     *
1411
     * @return the prepared statement
1412
     *
1413
     * @throws SQLException
1414
     *           the SQL exception
1415
     */
1416
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
1417
        throws SQLException {
1418
      return getValidConnection().prepareCall(sql, resultSetType, resultSetConcurrency);
×
1419
    }
1420

1421
    /**
1422
     * Prepare call.
1423
     *
1424
     * @param sql
1425
     *          the sql
1426
     * @param resultSetType
1427
     *          the result set type
1428
     * @param resultSetConcurrency
1429
     *          the result set concurrency
1430
     *
1431
     * @return the callable statement
1432
     *
1433
     * @throws SQLException
1434
     *           the SQL exception
1435
     */
1436
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
1437
      return getValidConnection().prepareCall(sql, resultSetType, resultSetConcurrency);
×
1438
    }
1439

1440
    /**
1441
     * Gets the type map.
1442
     *
1443
     * @return the type map
1444
     *
1445
     * @throws SQLException
1446
     *           the SQL exception
1447
     */
1448
    public Map getTypeMap() throws SQLException {
1449
      return getValidConnection().getTypeMap();
×
1450
    }
1451

1452
    /**
1453
     * Sets the type map.
1454
     *
1455
     * @param map
1456
     *          the new type map
1457
     *
1458
     * @throws SQLException
1459
     *           the SQL exception
1460
     */
1461
    public void setTypeMap(Map map) throws SQLException {
1462
      getValidConnection().setTypeMap(map);
×
1463
    }
×
1464

1465
    // **********************************
1466
    // JDK 1.4 JDBC 3.0 Methods below
1467
    // **********************************
1468

1469
    /**
1470
     * Sets the holdability.
1471
     *
1472
     * @param holdability
1473
     *          the new holdability
1474
     *
1475
     * @throws SQLException
1476
     *           the SQL exception
1477
     */
1478
    public void setHoldability(int holdability) throws SQLException {
1479
      getValidConnection().setHoldability(holdability);
×
1480
    }
×
1481

1482
    /**
1483
     * Gets the holdability.
1484
     *
1485
     * @return the holdability
1486
     *
1487
     * @throws SQLException
1488
     *           the SQL exception
1489
     */
1490
    public int getHoldability() throws SQLException {
1491
      return getValidConnection().getHoldability();
×
1492
    }
1493

1494
    /**
1495
     * Sets the savepoint.
1496
     *
1497
     * @return the savepoint
1498
     *
1499
     * @throws SQLException
1500
     *           the SQL exception
1501
     */
1502
    public Savepoint setSavepoint() throws SQLException {
1503
      return getValidConnection().setSavepoint();
×
1504
    }
1505

1506
    /**
1507
     * Sets the savepoint.
1508
     *
1509
     * @param name
1510
     *          the name
1511
     *
1512
     * @return the savepoint
1513
     *
1514
     * @throws SQLException
1515
     *           the SQL exception
1516
     */
1517
    public Savepoint setSavepoint(String name) throws SQLException {
1518
      return getValidConnection().setSavepoint(name);
×
1519
    }
1520

1521
    /**
1522
     * Rollback.
1523
     *
1524
     * @param savepoint
1525
     *          the savepoint
1526
     *
1527
     * @throws SQLException
1528
     *           the SQL exception
1529
     */
1530
    public void rollback(Savepoint savepoint) throws SQLException {
1531
      getValidConnection().rollback(savepoint);
×
1532
    }
×
1533

1534
    /**
1535
     * Release savepoint.
1536
     *
1537
     * @param savepoint
1538
     *          the savepoint
1539
     *
1540
     * @throws SQLException
1541
     *           the SQL exception
1542
     */
1543
    public void releaseSavepoint(Savepoint savepoint) throws SQLException {
1544
      getValidConnection().releaseSavepoint(savepoint);
×
1545
    }
×
1546

1547
    /**
1548
     * Creates the statement.
1549
     *
1550
     * @param resultSetType
1551
     *          the result set type
1552
     * @param resultSetConcurrency
1553
     *          the result set concurrency
1554
     * @param resultSetHoldability
1555
     *          the result set holdability
1556
     *
1557
     * @return the statement
1558
     *
1559
     * @throws SQLException
1560
     *           the SQL exception
1561
     */
1562
    public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
1563
        throws SQLException {
1564
      return getValidConnection().createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
×
1565
    }
1566

1567
    /**
1568
     * Prepare statement.
1569
     *
1570
     * @param sql
1571
     *          the sql
1572
     * @param resultSetType
1573
     *          the result set type
1574
     * @param resultSetConcurrency
1575
     *          the result set concurrency
1576
     * @param resultSetHoldability
1577
     *          the result set holdability
1578
     *
1579
     * @return the prepared statement
1580
     *
1581
     * @throws SQLException
1582
     *           the SQL exception
1583
     */
1584
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,
1585
        int resultSetHoldability) throws SQLException {
1586
      return getValidConnection().prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
×
1587
    }
1588

1589
    /**
1590
     * Prepare call.
1591
     *
1592
     * @param sql
1593
     *          the sql
1594
     * @param resultSetType
1595
     *          the result set type
1596
     * @param resultSetConcurrency
1597
     *          the result set concurrency
1598
     * @param resultSetHoldability
1599
     *          the result set holdability
1600
     *
1601
     * @return the callable statement
1602
     *
1603
     * @throws SQLException
1604
     *           the SQL exception
1605
     */
1606
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,
1607
        int resultSetHoldability) throws SQLException {
1608
      return getValidConnection().prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
×
1609
    }
1610

1611
    /**
1612
     * Prepare statement.
1613
     *
1614
     * @param sql
1615
     *          the sql
1616
     * @param autoGeneratedKeys
1617
     *          the auto generated keys
1618
     *
1619
     * @return the prepared statement
1620
     *
1621
     * @throws SQLException
1622
     *           the SQL exception
1623
     */
1624
    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
1625
      return getValidConnection().prepareStatement(sql, autoGeneratedKeys);
×
1626
    }
1627

1628
    /**
1629
     * Prepare statement.
1630
     *
1631
     * @param sql
1632
     *          the sql
1633
     * @param columnIndexes
1634
     *          the column indexes
1635
     *
1636
     * @return the prepared statement
1637
     *
1638
     * @throws SQLException
1639
     *           the SQL exception
1640
     */
1641
    public PreparedStatement prepareStatement(String sql, int columnIndexes[]) throws SQLException {
1642
      return getValidConnection().prepareStatement(sql, columnIndexes);
×
1643
    }
1644

1645
    /**
1646
     * Prepare statement.
1647
     *
1648
     * @param sql
1649
     *          the sql
1650
     * @param columnNames
1651
     *          the column names
1652
     *
1653
     * @return the prepared statement
1654
     *
1655
     * @throws SQLException
1656
     *           the SQL exception
1657
     */
1658
    public PreparedStatement prepareStatement(String sql, String columnNames[]) throws SQLException {
1659
      return getValidConnection().prepareStatement(sql, columnNames);
×
1660
    }
1661

1662
  }
1663

1664
  @Override
1665
  public Logger getParentLogger() throws SQLFeatureNotSupportedException {
1666
    // TODO Auto-generated method stub
1667
    return null;
×
1668
  }
1669

1670
  @Override
1671
  public <T> T unwrap(Class<T> iface) throws SQLException {
1672
    // TODO Auto-generated method stub
1673
    return null;
×
1674
  }
1675

1676
  @Override
1677
  public boolean isWrapperFor(Class<?> iface) throws SQLException {
1678
    // TODO Auto-generated method stub
1679
    return false;
×
1680
  }
1681
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc