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

mybatis / ibatis-2 / 730

28 Dec 2025 10:16PM UTC coverage: 65.615% (+0.5%) from 65.146%
730

push

github

web-flow
Update README.md

1602 of 2802 branches covered (57.17%)

5053 of 7701 relevant lines covered (65.61%)

0.66 hits per line

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

42.86
/src/main/java/com/ibatis/common/jdbc/SimpleDataSource.java
1
/*
2
 * Copyright 2004-2025 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!
220
        throw new RuntimeException("SimpleDataSource: Some properties were not set.");
×
221
      } else {
222

223
        jdbcDriver = (String) props.get(PROP_JDBC_DRIVER);
1✔
224
        jdbcUrl = (String) props.get(PROP_JDBC_URL);
1✔
225
        jdbcUsername = (String) props.get(PROP_JDBC_USERNAME);
1✔
226
        jdbcPassword = (String) props.get(PROP_JDBC_PASSWORD);
1✔
227

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

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

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

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

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

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

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

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

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

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

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

271
        Resources.instantiate(jdbcDriver);
1✔
272

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

791
    }
792

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

801
    return conn;
1✔
802
  }
803

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

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

824
    if (result) {
1!
825
      if (poolPingEnabled) {
1!
826
        if ((poolPingConnectionsOlderThan > 0 && conn.getAge() > poolPingConnectionsOlderThan)
×
827
            || (poolPingConnectionsNotUsedFor > 0
828
                && conn.getTimeElapsedSinceLastUse() > poolPingConnectionsNotUsedFor)) {
×
829

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

864
  /**
865
   * Unwraps a pooled connection to get to the 'real' connection.
866
   *
867
   * @param conn
868
   *          - the pooled connection to unwrap
869
   *
870
   * @return The 'real' connection
871
   */
872
  public static Connection unwrapConnection(Connection conn) {
873
    if (conn instanceof SimplePooledConnection) {
×
874
      return ((SimplePooledConnection) conn).getRealConnection();
×
875
    }
876
    return conn;
×
877
  }
878

879
  @Override
880
  protected void finalize() throws Throwable {
881
    forceCloseAll();
1✔
882
  }
1✔
883

884
  /**
885
   * --------------------------------------------------------------------------------------- SimplePooledConnection
886
   * ---------------------------------------------------------------------------------------.
887
   */
888
  public static class SimplePooledConnection implements InvocationHandler {
889

890
    /** The Constant CLOSE. */
891
    private static final String CLOSE = "close";
892

893
    /** The Constant IFACES. */
894
    private static final Class[] IFACES = { Connection.class };
1✔
895

896
    /** The hash code. */
897
    private int hashCode = 0;
1✔
898

899
    /** The data source. */
900
    private SimpleDataSource dataSource;
901

902
    /** The real connection. */
903
    private Connection realConnection;
904

905
    /** The proxy connection. */
906
    private Connection proxyConnection;
907

908
    /** The checkout timestamp. */
909
    private long checkoutTimestamp;
910

911
    /** The created timestamp. */
912
    private long createdTimestamp;
913

914
    /** The last used timestamp. */
915
    private long lastUsedTimestamp;
916

917
    /** The connection type code. */
918
    private int connectionTypeCode;
919

920
    /** The valid. */
921
    private boolean valid;
922

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

939
      proxyConnection = (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(), IFACES, this);
1✔
940
    }
1✔
941

942
    /**
943
     * Invalidates the connection.
944
     */
945
    public void invalidate() {
946
      valid = false;
1✔
947
    }
1✔
948

949
    /**
950
     * Method to see if the connection is usable.
951
     *
952
     * @return True if the connection is usable
953
     */
954
    public boolean isValid() {
955
      return valid && realConnection != null && dataSource.pingConnection(this);
1!
956
    }
957

958
    /**
959
     * Getter for the *real* connection that this wraps.
960
     *
961
     * @return The connection
962
     */
963
    public Connection getRealConnection() {
964
      return realConnection;
1✔
965
    }
966

967
    /**
968
     * Getter for the proxy for the connection.
969
     *
970
     * @return The proxy
971
     */
972
    public Connection getProxyConnection() {
973
      return proxyConnection;
1✔
974
    }
975

976
    /**
977
     * Gets the hashcode of the real connection (or 0 if it is null).
978
     *
979
     * @return The hashcode of the real connection (or 0 if it is null)
980
     */
981
    public int getRealHashCode() {
982
      if (realConnection == null) {
×
983
        return 0;
×
984
      }
985
      return realConnection.hashCode();
×
986
    }
987

988
    /**
989
     * Getter for the connection type (based on url + user + password).
990
     *
991
     * @return The connection type
992
     */
993
    public int getConnectionTypeCode() {
994
      return connectionTypeCode;
1✔
995
    }
996

997
    /**
998
     * Setter for the connection type.
999
     *
1000
     * @param connectionTypeCode
1001
     *          - the connection type
1002
     */
1003
    public void setConnectionTypeCode(int connectionTypeCode) {
1004
      this.connectionTypeCode = connectionTypeCode;
1✔
1005
    }
1✔
1006

1007
    /**
1008
     * Getter for the time that the connection was created.
1009
     *
1010
     * @return The creation timestamp
1011
     */
1012
    public long getCreatedTimestamp() {
1013
      return createdTimestamp;
1✔
1014
    }
1015

1016
    /**
1017
     * Setter for the time that the connection was created.
1018
     *
1019
     * @param createdTimestamp
1020
     *          - the timestamp
1021
     */
1022
    public void setCreatedTimestamp(long createdTimestamp) {
1023
      this.createdTimestamp = createdTimestamp;
1✔
1024
    }
1✔
1025

1026
    /**
1027
     * Getter for the time that the connection was last used.
1028
     *
1029
     * @return - the timestamp
1030
     */
1031
    public long getLastUsedTimestamp() {
1032
      return lastUsedTimestamp;
1✔
1033
    }
1034

1035
    /**
1036
     * Setter for the time that the connection was last used.
1037
     *
1038
     * @param lastUsedTimestamp
1039
     *          - the timestamp
1040
     */
1041
    public void setLastUsedTimestamp(long lastUsedTimestamp) {
1042
      this.lastUsedTimestamp = lastUsedTimestamp;
1✔
1043
    }
1✔
1044

1045
    /**
1046
     * Getter for the time since this connection was last used.
1047
     *
1048
     * @return - the time since the last use
1049
     */
1050
    public long getTimeElapsedSinceLastUse() {
1051
      return System.currentTimeMillis() - lastUsedTimestamp;
×
1052
    }
1053

1054
    /**
1055
     * Getter for the age of the connection.
1056
     *
1057
     * @return the age
1058
     */
1059
    public long getAge() {
1060
      return System.currentTimeMillis() - createdTimestamp;
×
1061
    }
1062

1063
    /**
1064
     * Getter for the timestamp that this connection was checked out.
1065
     *
1066
     * @return the timestamp
1067
     */
1068
    public long getCheckoutTimestamp() {
1069
      return checkoutTimestamp;
×
1070
    }
1071

1072
    /**
1073
     * Setter for the timestamp that this connection was checked out.
1074
     *
1075
     * @param timestamp
1076
     *          the timestamp
1077
     */
1078
    public void setCheckoutTimestamp(long timestamp) {
1079
      this.checkoutTimestamp = timestamp;
1✔
1080
    }
1✔
1081

1082
    /**
1083
     * Getter for the time that this connection has been checked out.
1084
     *
1085
     * @return the time
1086
     */
1087
    public long getCheckoutTime() {
1088
      return System.currentTimeMillis() - checkoutTimestamp;
1✔
1089
    }
1090

1091
    /**
1092
     * Gets the valid connection.
1093
     *
1094
     * @return the valid connection
1095
     */
1096
    private Connection getValidConnection() {
1097
      if (!valid) {
1!
1098
        throw new RuntimeException("Error accessing SimplePooledConnection. Connection is invalid.");
×
1099
      }
1100
      return realConnection;
1✔
1101
    }
1102

1103
    @Override
1104
    public int hashCode() {
1105
      return hashCode;
×
1106
    }
1107

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

1127
    // **********************************
1128
    // Implemented Connection Methods -- Now handled by proxy
1129
    // **********************************
1130

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

1158
    /**
1159
     * Creates the statement.
1160
     *
1161
     * @return the statement
1162
     *
1163
     * @throws SQLException
1164
     *           the SQL exception
1165
     */
1166
    public Statement createStatement() throws SQLException {
1167
      return getValidConnection().createStatement();
×
1168
    }
1169

1170
    /**
1171
     * Prepare statement.
1172
     *
1173
     * @param sql
1174
     *          the sql
1175
     *
1176
     * @return the prepared statement
1177
     *
1178
     * @throws SQLException
1179
     *           the SQL exception
1180
     */
1181
    public PreparedStatement prepareStatement(String sql) throws SQLException {
1182
      return getValidConnection().prepareStatement(sql);
×
1183
    }
1184

1185
    /**
1186
     * Prepare call.
1187
     *
1188
     * @param sql
1189
     *          the sql
1190
     *
1191
     * @return the callable statement
1192
     *
1193
     * @throws SQLException
1194
     *           the SQL exception
1195
     */
1196
    public CallableStatement prepareCall(String sql) throws SQLException {
1197
      return getValidConnection().prepareCall(sql);
×
1198
    }
1199

1200
    /**
1201
     * Native SQL.
1202
     *
1203
     * @param sql
1204
     *          the sql
1205
     *
1206
     * @return the string
1207
     *
1208
     * @throws SQLException
1209
     *           the SQL exception
1210
     */
1211
    public String nativeSQL(String sql) throws SQLException {
1212
      return getValidConnection().nativeSQL(sql);
×
1213
    }
1214

1215
    /**
1216
     * Sets the auto commit.
1217
     *
1218
     * @param autoCommit
1219
     *          the new auto commit
1220
     *
1221
     * @throws SQLException
1222
     *           the SQL exception
1223
     */
1224
    public void setAutoCommit(boolean autoCommit) throws SQLException {
1225
      getValidConnection().setAutoCommit(autoCommit);
×
1226
    }
×
1227

1228
    /**
1229
     * Gets the auto commit.
1230
     *
1231
     * @return the auto commit
1232
     *
1233
     * @throws SQLException
1234
     *           the SQL exception
1235
     */
1236
    public boolean getAutoCommit() throws SQLException {
1237
      return getValidConnection().getAutoCommit();
×
1238
    }
1239

1240
    /**
1241
     * Commit.
1242
     *
1243
     * @throws SQLException
1244
     *           the SQL exception
1245
     */
1246
    public void commit() throws SQLException {
1247
      getValidConnection().commit();
×
1248
    }
×
1249

1250
    /**
1251
     * Rollback.
1252
     *
1253
     * @throws SQLException
1254
     *           the SQL exception
1255
     */
1256
    public void rollback() throws SQLException {
1257
      getValidConnection().rollback();
×
1258
    }
×
1259

1260
    /**
1261
     * Close.
1262
     *
1263
     * @throws SQLException
1264
     *           the SQL exception
1265
     */
1266
    public void close() throws SQLException {
1267
      dataSource.pushConnection(this);
×
1268
    }
×
1269

1270
    /**
1271
     * Checks if is closed.
1272
     *
1273
     * @return true, if is closed
1274
     *
1275
     * @throws SQLException
1276
     *           the SQL exception
1277
     */
1278
    public boolean isClosed() throws SQLException {
1279
      return getValidConnection().isClosed();
×
1280
    }
1281

1282
    /**
1283
     * Gets the meta data.
1284
     *
1285
     * @return the meta data
1286
     *
1287
     * @throws SQLException
1288
     *           the SQL exception
1289
     */
1290
    public DatabaseMetaData getMetaData() throws SQLException {
1291
      return getValidConnection().getMetaData();
×
1292
    }
1293

1294
    /**
1295
     * Sets the read only.
1296
     *
1297
     * @param readOnly
1298
     *          the new read only
1299
     *
1300
     * @throws SQLException
1301
     *           the SQL exception
1302
     */
1303
    public void setReadOnly(boolean readOnly) throws SQLException {
1304
      getValidConnection().setReadOnly(readOnly);
×
1305
    }
×
1306

1307
    /**
1308
     * Checks if is read only.
1309
     *
1310
     * @return true, if is read only
1311
     *
1312
     * @throws SQLException
1313
     *           the SQL exception
1314
     */
1315
    public boolean isReadOnly() throws SQLException {
1316
      return getValidConnection().isReadOnly();
×
1317
    }
1318

1319
    /**
1320
     * Sets the catalog.
1321
     *
1322
     * @param catalog
1323
     *          the new catalog
1324
     *
1325
     * @throws SQLException
1326
     *           the SQL exception
1327
     */
1328
    public void setCatalog(String catalog) throws SQLException {
1329
      getValidConnection().setCatalog(catalog);
×
1330
    }
×
1331

1332
    /**
1333
     * Gets the catalog.
1334
     *
1335
     * @return the catalog
1336
     *
1337
     * @throws SQLException
1338
     *           the SQL exception
1339
     */
1340
    public String getCatalog() throws SQLException {
1341
      return getValidConnection().getCatalog();
×
1342
    }
1343

1344
    /**
1345
     * Sets the transaction isolation.
1346
     *
1347
     * @param level
1348
     *          the new transaction isolation
1349
     *
1350
     * @throws SQLException
1351
     *           the SQL exception
1352
     */
1353
    public void setTransactionIsolation(int level) throws SQLException {
1354
      getValidConnection().setTransactionIsolation(level);
×
1355
    }
×
1356

1357
    /**
1358
     * Gets the transaction isolation.
1359
     *
1360
     * @return the transaction isolation
1361
     *
1362
     * @throws SQLException
1363
     *           the SQL exception
1364
     */
1365
    public int getTransactionIsolation() throws SQLException {
1366
      return getValidConnection().getTransactionIsolation();
×
1367
    }
1368

1369
    /**
1370
     * Gets the warnings.
1371
     *
1372
     * @return the warnings
1373
     *
1374
     * @throws SQLException
1375
     *           the SQL exception
1376
     */
1377
    public SQLWarning getWarnings() throws SQLException {
1378
      return getValidConnection().getWarnings();
×
1379
    }
1380

1381
    /**
1382
     * Clear warnings.
1383
     *
1384
     * @throws SQLException
1385
     *           the SQL exception
1386
     */
1387
    public void clearWarnings() throws SQLException {
1388
      getValidConnection().clearWarnings();
×
1389
    }
×
1390

1391
    /**
1392
     * Creates the statement.
1393
     *
1394
     * @param resultSetType
1395
     *          the result set type
1396
     * @param resultSetConcurrency
1397
     *          the result set concurrency
1398
     *
1399
     * @return the statement
1400
     *
1401
     * @throws SQLException
1402
     *           the SQL exception
1403
     */
1404
    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
1405
      return getValidConnection().createStatement(resultSetType, resultSetConcurrency);
×
1406
    }
1407

1408
    /**
1409
     * Prepare statement.
1410
     *
1411
     * @param sql
1412
     *          the sql
1413
     * @param resultSetType
1414
     *          the result set type
1415
     * @param resultSetConcurrency
1416
     *          the result set concurrency
1417
     *
1418
     * @return the prepared statement
1419
     *
1420
     * @throws SQLException
1421
     *           the SQL exception
1422
     */
1423
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
1424
        throws SQLException {
1425
      return getValidConnection().prepareCall(sql, resultSetType, resultSetConcurrency);
×
1426
    }
1427

1428
    /**
1429
     * Prepare call.
1430
     *
1431
     * @param sql
1432
     *          the sql
1433
     * @param resultSetType
1434
     *          the result set type
1435
     * @param resultSetConcurrency
1436
     *          the result set concurrency
1437
     *
1438
     * @return the callable statement
1439
     *
1440
     * @throws SQLException
1441
     *           the SQL exception
1442
     */
1443
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
1444
      return getValidConnection().prepareCall(sql, resultSetType, resultSetConcurrency);
×
1445
    }
1446

1447
    /**
1448
     * Gets the type map.
1449
     *
1450
     * @return the type map
1451
     *
1452
     * @throws SQLException
1453
     *           the SQL exception
1454
     */
1455
    public Map getTypeMap() throws SQLException {
1456
      return getValidConnection().getTypeMap();
×
1457
    }
1458

1459
    /**
1460
     * Sets the type map.
1461
     *
1462
     * @param map
1463
     *          the new type map
1464
     *
1465
     * @throws SQLException
1466
     *           the SQL exception
1467
     */
1468
    public void setTypeMap(Map map) throws SQLException {
1469
      getValidConnection().setTypeMap(map);
×
1470
    }
×
1471

1472
    // **********************************
1473
    // JDK 1.4 JDBC 3.0 Methods below
1474
    // **********************************
1475

1476
    /**
1477
     * Sets the holdability.
1478
     *
1479
     * @param holdability
1480
     *          the new holdability
1481
     *
1482
     * @throws SQLException
1483
     *           the SQL exception
1484
     */
1485
    public void setHoldability(int holdability) throws SQLException {
1486
      getValidConnection().setHoldability(holdability);
×
1487
    }
×
1488

1489
    /**
1490
     * Gets the holdability.
1491
     *
1492
     * @return the holdability
1493
     *
1494
     * @throws SQLException
1495
     *           the SQL exception
1496
     */
1497
    public int getHoldability() throws SQLException {
1498
      return getValidConnection().getHoldability();
×
1499
    }
1500

1501
    /**
1502
     * Sets the savepoint.
1503
     *
1504
     * @return the savepoint
1505
     *
1506
     * @throws SQLException
1507
     *           the SQL exception
1508
     */
1509
    public Savepoint setSavepoint() throws SQLException {
1510
      return getValidConnection().setSavepoint();
×
1511
    }
1512

1513
    /**
1514
     * Sets the savepoint.
1515
     *
1516
     * @param name
1517
     *          the name
1518
     *
1519
     * @return the savepoint
1520
     *
1521
     * @throws SQLException
1522
     *           the SQL exception
1523
     */
1524
    public Savepoint setSavepoint(String name) throws SQLException {
1525
      return getValidConnection().setSavepoint(name);
×
1526
    }
1527

1528
    /**
1529
     * Rollback.
1530
     *
1531
     * @param savepoint
1532
     *          the savepoint
1533
     *
1534
     * @throws SQLException
1535
     *           the SQL exception
1536
     */
1537
    public void rollback(Savepoint savepoint) throws SQLException {
1538
      getValidConnection().rollback(savepoint);
×
1539
    }
×
1540

1541
    /**
1542
     * Release savepoint.
1543
     *
1544
     * @param savepoint
1545
     *          the savepoint
1546
     *
1547
     * @throws SQLException
1548
     *           the SQL exception
1549
     */
1550
    public void releaseSavepoint(Savepoint savepoint) throws SQLException {
1551
      getValidConnection().releaseSavepoint(savepoint);
×
1552
    }
×
1553

1554
    /**
1555
     * Creates the statement.
1556
     *
1557
     * @param resultSetType
1558
     *          the result set type
1559
     * @param resultSetConcurrency
1560
     *          the result set concurrency
1561
     * @param resultSetHoldability
1562
     *          the result set holdability
1563
     *
1564
     * @return the statement
1565
     *
1566
     * @throws SQLException
1567
     *           the SQL exception
1568
     */
1569
    public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
1570
        throws SQLException {
1571
      return getValidConnection().createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
×
1572
    }
1573

1574
    /**
1575
     * Prepare statement.
1576
     *
1577
     * @param sql
1578
     *          the sql
1579
     * @param resultSetType
1580
     *          the result set type
1581
     * @param resultSetConcurrency
1582
     *          the result set concurrency
1583
     * @param resultSetHoldability
1584
     *          the result set holdability
1585
     *
1586
     * @return the prepared statement
1587
     *
1588
     * @throws SQLException
1589
     *           the SQL exception
1590
     */
1591
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,
1592
        int resultSetHoldability) throws SQLException {
1593
      return getValidConnection().prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
×
1594
    }
1595

1596
    /**
1597
     * Prepare call.
1598
     *
1599
     * @param sql
1600
     *          the sql
1601
     * @param resultSetType
1602
     *          the result set type
1603
     * @param resultSetConcurrency
1604
     *          the result set concurrency
1605
     * @param resultSetHoldability
1606
     *          the result set holdability
1607
     *
1608
     * @return the callable statement
1609
     *
1610
     * @throws SQLException
1611
     *           the SQL exception
1612
     */
1613
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,
1614
        int resultSetHoldability) throws SQLException {
1615
      return getValidConnection().prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
×
1616
    }
1617

1618
    /**
1619
     * Prepare statement.
1620
     *
1621
     * @param sql
1622
     *          the sql
1623
     * @param autoGeneratedKeys
1624
     *          the auto generated keys
1625
     *
1626
     * @return the prepared statement
1627
     *
1628
     * @throws SQLException
1629
     *           the SQL exception
1630
     */
1631
    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
1632
      return getValidConnection().prepareStatement(sql, autoGeneratedKeys);
×
1633
    }
1634

1635
    /**
1636
     * Prepare statement.
1637
     *
1638
     * @param sql
1639
     *          the sql
1640
     * @param columnIndexes
1641
     *          the column indexes
1642
     *
1643
     * @return the prepared statement
1644
     *
1645
     * @throws SQLException
1646
     *           the SQL exception
1647
     */
1648
    public PreparedStatement prepareStatement(String sql, int columnIndexes[]) throws SQLException {
1649
      return getValidConnection().prepareStatement(sql, columnIndexes);
×
1650
    }
1651

1652
    /**
1653
     * Prepare statement.
1654
     *
1655
     * @param sql
1656
     *          the sql
1657
     * @param columnNames
1658
     *          the column names
1659
     *
1660
     * @return the prepared statement
1661
     *
1662
     * @throws SQLException
1663
     *           the SQL exception
1664
     */
1665
    public PreparedStatement prepareStatement(String sql, String columnNames[]) throws SQLException {
1666
      return getValidConnection().prepareStatement(sql, columnNames);
×
1667
    }
1668

1669
  }
1670

1671
  @Override
1672
  public Logger getParentLogger() throws SQLFeatureNotSupportedException {
1673
    // TODO Auto-generated method stub
1674
    return null;
×
1675
  }
1676

1677
  @Override
1678
  public <T> T unwrap(Class<T> iface) throws SQLException {
1679
    // TODO Auto-generated method stub
1680
    return null;
×
1681
  }
1682

1683
  @Override
1684
  public boolean isWrapperFor(Class<?> iface) throws SQLException {
1685
    // TODO Auto-generated method stub
1686
    return false;
×
1687
  }
1688
}
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

© 2025 Coveralls, Inc