001package org.javasimon.jdbc4; 002 003import java.sql.Array; 004import java.sql.Blob; 005import java.sql.CallableStatement; 006import java.sql.Clob; 007import java.sql.Connection; 008import java.sql.DatabaseMetaData; 009import java.sql.NClob; 010import java.sql.PreparedStatement; 011import java.sql.SQLClientInfoException; 012import java.sql.SQLException; 013import java.sql.SQLWarning; 014import java.sql.SQLXML; 015import java.sql.Savepoint; 016import java.sql.Statement; 017import java.sql.Struct; 018import java.util.Map; 019import java.util.Properties; 020import java.util.concurrent.Executor; 021 022import org.javasimon.Counter; 023import org.javasimon.SimonManager; 024import org.javasimon.Split; 025 026/** 027 * Class implements Simon JDBC proxy connection. 028 * <p> 029 * Every method of this connection is implemented as call of real connection method. 030 * Several methods have added work with Simons (starting, stopping, etc.) for monitoring 031 * purposes. 032 * </p> 033 * <p> 034 * From all statement-return-methods (<code>createStatement(*)</code>, 035 * <code>prepareStatement(*)</code>, <code>prepareCall(*)</code>) connection returns own 036 * implementation of statement classes. Those classes are also proxies and provides 037 * additional Simons for monitoring features of JDBC driver. 038 * </p> 039 * Monitoring connection ensure following Simons: 040 * <ul> 041 * <li>lifespan (<code>org.javasimon.jdbc4.conn</code>, stopwatch) - measure connection life and count</li> 042 * <li>commits (<code>org.javasimon.jdbc4.conn.commits</code>, counter) - measure executed commits of all connections</li> 043 * <li>rollbacks (<code>org.javasimon.jdbc4.conn.rollbacks</code>, counter) - measure executed rollbacks of all connections</li> 044 * </ul> 045 * 046 * @author Radovan Sninsky 047 * @see java.sql.Connection 048 * @since 2.4 049 */ 050public final class SimonConnection implements Connection { 051 private final Connection conn; 052 private final WrapperSupport<Connection> wrapperSupport; 053 private String prefix; 054 055 private Split life; 056 private Counter commits; 057 private Counter rollbacks; 058 059 /** 060 * Class constructor, initializes Simons (lifespan, active, commits 061 * and rollbacks) related to the DB connection. 062 * 063 * @param conn real DB connection 064 * @param prefix hierarchy prefix for connection Simons 065 */ 066 public SimonConnection(Connection conn, String prefix) { 067 this.conn = conn; 068 this.wrapperSupport = new WrapperSupport<>(this.conn, Connection.class); 069 this.prefix = prefix; 070 071 commits = SimonManager.getCounter(prefix + ".conn.commits"); 072 rollbacks = SimonManager.getCounter(prefix + ".conn.rollbacks"); 073 life = SimonManager.getStopwatch(prefix + ".conn").start(); 074 } 075 076 /** 077 * Closes the real connection, stops lifespan Simon and decreases the active Simon. 078 * 079 * @throws java.sql.SQLException if real operation fails 080 */ 081 @Override 082 public void close() throws SQLException { 083 conn.close(); 084 085 life.stop(); 086 } 087 088 /** 089 * Commits the real connection and increases the commits Simon. 090 * 091 * @throws java.sql.SQLException if real commit fails 092 */ 093 @Override 094 public void commit() throws SQLException { 095 conn.commit(); 096 097 commits.increase(); 098 } 099 100 /** 101 * Rollback the real connection and increase the rollbacks Simon. 102 * 103 * @throws java.sql.SQLException if real operation fails 104 */ 105 @Override 106 public void rollback() throws SQLException { 107 conn.rollback(); 108 109 rollbacks.increase(); 110 } 111 112 /** 113 * Rollbacks the real connection and increases the rollbacks Simon. 114 * 115 * @param savepoint the <code>Savepoint</code> object to roll back to 116 * @throws java.sql.SQLException if real operation fails 117 */ 118 @Override 119 public void rollback(Savepoint savepoint) throws SQLException { 120 conn.rollback(savepoint); 121 122 rollbacks.increase(); 123 } 124 125 /** 126 * Calls the real createStatement and wraps the returned statement by Simon's statement. 127 * 128 * @return Simon's statement with wrapped real statement 129 * @throws java.sql.SQLException if real operation fails 130 */ 131 @Override 132 public Statement createStatement() throws SQLException { 133 return new SimonStatement(this, conn.createStatement(), prefix); 134 } 135 136 /** 137 * Calls real createStatement and wraps returned statement by Simon's statement. 138 * 139 * @param rsType result set type 140 * @param rsConcurrency result set concurrency 141 * @return Simon's statement with wrapped real statement 142 * @throws java.sql.SQLException if real operation fails 143 */ 144 @Override 145 public Statement createStatement(int rsType, int rsConcurrency) throws SQLException { 146 return new SimonStatement(this, conn.createStatement(rsType, rsConcurrency), prefix); 147 } 148 149 /** 150 * Calls real createStatement and wraps returned statement by Simon's statement. 151 * 152 * @param rsType result set type 153 * @param rsConcurrency result set concurrency 154 * @param rsHoldability result set holdability 155 * @return Simon's statement with wrapped real statement 156 * @throws java.sql.SQLException if real operation fails 157 */ 158 @Override 159 public Statement createStatement(int rsType, int rsConcurrency, int rsHoldability) throws SQLException { 160 return new SimonStatement(this, conn.createStatement(rsType, rsConcurrency, rsHoldability), prefix); 161 } 162 163 /** 164 * Calls real prepareStatement and wraps returned statement by Simon's statement. 165 * 166 * @param sql SQL statement 167 * @return Simon's statement with wrapped real statement 168 * @throws java.sql.SQLException if real operation fails 169 */ 170 @Override 171 public PreparedStatement prepareStatement(String sql) throws SQLException { 172 return new SimonPreparedStatement(this, conn.prepareStatement(sql), sql, prefix); 173 } 174 175 /** 176 * Calls real prepareStatement and wraps returned statement by Simon's statement. 177 * 178 * @param sql SQL statement 179 * @param autoGeneratedKeys auto generated keys 180 * @return Simon's statement with wrapped real statement 181 * @throws java.sql.SQLException if real operation fails 182 */ 183 @Override 184 public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { 185 return new SimonPreparedStatement(this, conn.prepareStatement(sql, autoGeneratedKeys), sql, prefix); 186 } 187 188 /** 189 * Calls real prepareStatement and wraps returned statement by Simon's statement. 190 * 191 * @param sql SQL statement 192 * @param rsType result set type 193 * @param rsConcurrency result set concurrency 194 * @return Simon's statement with wrapped real statement 195 * @throws java.sql.SQLException if real operation fails 196 */ 197 @Override 198 public PreparedStatement prepareStatement(String sql, int rsType, int rsConcurrency) throws SQLException { 199 return new SimonPreparedStatement(this, conn.prepareStatement(sql, rsType, rsConcurrency), sql, prefix); 200 } 201 202 /** 203 * Calls real prepareStatement and wraps returned statement by Simon's statement. 204 * 205 * @param sql SQL statement 206 * @param rsType result set type 207 * @param rsConcurrency result set concurrency 208 * @param rsHoldability result set holdability 209 * @return Simon's statement with wrapped real statement 210 * @throws java.sql.SQLException if real operation fails 211 */ 212 @Override 213 public PreparedStatement prepareStatement(String sql, int rsType, int rsConcurrency, int rsHoldability) throws SQLException { 214 return new SimonPreparedStatement(this, conn.prepareStatement(sql, rsType, rsConcurrency, rsHoldability), sql, prefix); 215 } 216 217 /** 218 * Calls real prepareStatement and wraps returned statement by Simon's statement. 219 * 220 * @param sql SQL statement 221 * @param columnIndexes an array of column indexes indicating the columns 222 * that should be returned from the inserted row or rows 223 * @return Simon's statement with wrapped real statement 224 * @throws java.sql.SQLException if real operation fails 225 */ 226 @Override 227 public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { 228 return new SimonPreparedStatement(this, conn.prepareStatement(sql, columnIndexes), sql, prefix); 229 } 230 231 /** 232 * Calls real prepareStatement and wraps returned statement by Simon's statement. 233 * 234 * @param sql SQL statement 235 * @param columnNames an array of column names indicating the columns 236 * that should be returned from the inserted row or rows 237 * @return Simon's statement with wrapped real statement 238 * @throws java.sql.SQLException if real operation fails 239 */ 240 @Override 241 public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { 242 return new SimonPreparedStatement(this, conn.prepareStatement(sql, columnNames), sql, prefix); 243 } 244 245 /** 246 * Calls real prepareCall and wraps returned statement by Simon's statement. 247 * 248 * @param sql an SQL statement, typically a JDBC function call escape string 249 * @return Simon's statement with wrapped real statement 250 * @throws java.sql.SQLException if real operation fails 251 */ 252 @Override 253 public CallableStatement prepareCall(String sql) throws SQLException { 254 return new SimonCallableStatement(conn, conn.prepareCall(sql), sql, prefix); 255 } 256 257 /** 258 * Calls real prepareCall and wraps returned statement by Simon's statement. 259 * 260 * @param sql an SQL statement, typically a JDBC function call escape string 261 * @param rsType result set type 262 * @param rsConcurrency result set concurrency 263 * @return Simon's statement with wrapped real statement 264 * @throws java.sql.SQLException if real operation fails 265 */ 266 @Override 267 public CallableStatement prepareCall(String sql, int rsType, int rsConcurrency) throws SQLException { 268 return new SimonCallableStatement(conn, conn.prepareCall(sql, rsType, rsConcurrency), sql, prefix); 269 } 270 271 /** 272 * Calls real prepareCall and wraps returned statement by Simon's statement. 273 * 274 * @param sql an SQL statement, typically a JDBC function call escape string 275 * @param rsType result set type 276 * @param rsConcurrency result set concurrency 277 * @param rsHoldability result set holdability 278 * @return Simon's statement with wrapped real statement 279 * @throws java.sql.SQLException if real operation fails 280 */ 281 @Override 282 public CallableStatement prepareCall(String sql, int rsType, int rsConcurrency, int rsHoldability) throws SQLException { 283 return new SimonCallableStatement(conn, conn.prepareCall(sql, rsType, rsConcurrency, rsHoldability), sql, prefix); 284 } 285 286 //// NOT MONITORED 287 288 @Override 289 public String nativeSQL(String s) throws SQLException { 290 return conn.nativeSQL(s); 291 } 292 293 @Override 294 public void setAutoCommit(boolean b) throws SQLException { 295 conn.setAutoCommit(b); 296 } 297 298 @Override 299 public boolean getAutoCommit() throws SQLException { 300 return conn.getAutoCommit(); 301 } 302 303 @Override 304 public boolean isClosed() throws SQLException { 305 return conn.isClosed(); 306 } 307 308 @Override 309 public DatabaseMetaData getMetaData() throws SQLException { 310 return conn.getMetaData(); 311 } 312 313 @Override 314 public void setReadOnly(boolean b) throws SQLException { 315 conn.setReadOnly(b); 316 } 317 318 @Override 319 public boolean isReadOnly() throws SQLException { 320 return conn.isReadOnly(); 321 } 322 323 @Override 324 public void setCatalog(String s) throws SQLException { 325 conn.setCatalog(s); 326 } 327 328 @Override 329 public String getCatalog() throws SQLException { 330 return conn.getCatalog(); 331 } 332 333 @Override 334 public void setTransactionIsolation(int i) throws SQLException { 335 conn.setTransactionIsolation(i); 336 } 337 338 @Override 339 public int getTransactionIsolation() throws SQLException { 340 return conn.getTransactionIsolation(); 341 } 342 343 @Override 344 public SQLWarning getWarnings() throws SQLException { 345 return conn.getWarnings(); 346 } 347 348 @Override 349 public void clearWarnings() throws SQLException { 350 conn.clearWarnings(); 351 } 352 353 @Override 354 public Map<String, Class<?>> getTypeMap() throws SQLException { 355 return conn.getTypeMap(); 356 } 357 358 @Override 359 public void setTypeMap(Map<String, Class<?>> stringClassMap) throws SQLException { 360 conn.setTypeMap(stringClassMap); 361 } 362 363 @Override 364 public void setHoldability(int i) throws SQLException { 365 conn.setHoldability(i); 366 } 367 368 @Override 369 public int getHoldability() throws SQLException { 370 return conn.getHoldability(); 371 } 372 373 @Override 374 public Savepoint setSavepoint() throws SQLException { 375 return conn.setSavepoint(); 376 } 377 378 @Override 379 public Savepoint setSavepoint(String s) throws SQLException { 380 return conn.setSavepoint(s); 381 } 382 383 @Override 384 public void releaseSavepoint(Savepoint savepoint) throws SQLException { 385 conn.releaseSavepoint(savepoint); 386 } 387 388 @Override 389 public Clob createClob() throws SQLException { 390 return conn.createClob(); 391 } 392 393 @Override 394 public Blob createBlob() throws SQLException { 395 return conn.createBlob(); 396 } 397 398 @Override 399 public NClob createNClob() throws SQLException { 400 return conn.createNClob(); 401 } 402 403 @Override 404 public SQLXML createSQLXML() throws SQLException { 405 return conn.createSQLXML(); 406 } 407 408 @Override 409 public boolean isValid(int i) throws SQLException { 410 return conn.isValid(i); 411 } 412 413 @Override 414 public void setClientInfo(String s, String s1) throws SQLClientInfoException { 415 conn.setClientInfo(s, s1); 416 } 417 418 @Override 419 public void setClientInfo(Properties properties) throws SQLClientInfoException { 420 conn.setClientInfo(properties); 421 } 422 423 @Override 424 public String getClientInfo(String s) throws SQLException { 425 return conn.getClientInfo(s); 426 } 427 428 @Override 429 public Properties getClientInfo() throws SQLException { 430 return conn.getClientInfo(); 431 } 432 433 @Override 434 public Array createArrayOf(String s, Object[] objects) throws SQLException { 435 return conn.createArrayOf(s, objects); 436 } 437 438 @Override 439 public Struct createStruct(String s, Object[] objects) throws SQLException { 440 return conn.createStruct(s, objects); 441 } 442 443 @Override 444 public void setSchema(String schema) throws SQLException { 445 conn.setSchema(schema); 446 } 447 448 @Override 449 public String getSchema() throws SQLException { 450 return conn.getSchema(); 451 } 452 453 @Override 454 public void abort(Executor executor) throws SQLException { 455 conn.abort(executor); 456 } 457 458 @Override 459 public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException { 460 conn.setNetworkTimeout(executor, milliseconds); 461 } 462 463 @Override 464 public int getNetworkTimeout() throws SQLException { 465 return conn.getNetworkTimeout(); 466 } 467 468 @Override 469 public <T> T unwrap(Class<T> iface) throws SQLException { 470 return wrapperSupport.unwrap(iface); 471 } 472 473 @Override 474 public boolean isWrapperFor(Class<?> iface) throws SQLException { 475 return wrapperSupport.isWrapperFor(iface); 476 } 477}