1 22 23 24 package com.mchange.v2.c3p0.codegen; 25 26 import java.io.*; 27 import java.lang.reflect.*; 28 import java.sql.*; 29 import com.mchange.v2.codegen.*; 30 import com.mchange.v2.codegen.intfc.*; 31 import com.mchange.v2.c3p0.C3P0ProxyConnection; 32 import com.mchange.v2.c3p0.C3P0ProxyStatement; 33 34 public abstract class JdbcProxyGenerator extends DelegatorGenerator 35 { 36 final static boolean PREMATURE_DETACH_DEBUG = false; 37 38 JdbcProxyGenerator() 39 { 40 this.setGenerateInnerSetter( false ); 41 this.setGenerateInnerGetter( false ); 42 this.setGenerateNoArgConstructor( false ); 43 this.setGenerateWrappingConstructor( true ); 44 this.setClassModifiers( Modifier.PUBLIC | Modifier.FINAL ); 45 this.setMethodModifiers( Modifier.PUBLIC | Modifier.FINAL ); 46 } 47 48 abstract String getInnerTypeName(); 49 50 static final class NewProxyMetaDataGenerator extends JdbcProxyGenerator 51 { 52 String getInnerTypeName() 53 { return "DatabaseMetaData"; } 54 55 protected void generateDelegateCode( Class intfcl, String genclass, Method method, IndentedWriter iw ) throws IOException 56 { 57 String mname = method.getName(); 58 Class retType = method.getReturnType(); 59 60 if ( ResultSet.class.isAssignableFrom( retType ) ) 61 { 62 iw.println("ResultSet innerResultSet = inner." + CodegenUtils.methodCall( method ) + ";"); 63 iw.println("if (innerResultSet == null) return null;"); 64 iw.println("return new NewProxyResultSet( innerResultSet, parentPooledConnection, inner, this );"); 65 } 66 else if ( mname.equals( "getConnection" ) ) 67 { 68 iw.println("return this.proxyCon;"); 69 } 70 else 71 super.generateDelegateCode( intfcl, genclass, method, iw ); 72 } 73 74 protected void generatePreDelegateCode( Class intfcl, String genclass, Method method, IndentedWriter iw ) throws IOException 75 { 76 if ( method.getExceptionTypes().length > 0 ) 77 super.generatePreDelegateCode( intfcl, genclass, method, iw ); 78 } 79 80 protected void generatePostDelegateCode( Class intfcl, String genclass, Method method, IndentedWriter iw ) throws IOException 81 { 82 if ( method.getExceptionTypes().length > 0 ) 83 super.generatePostDelegateCode( intfcl, genclass, method, iw ); 84 } 85 86 protected void generateExtraDeclarations( Class intfcl, String genclass, IndentedWriter iw ) throws IOException 87 { 88 super.generateExtraDeclarations( intfcl, genclass, iw ); 89 iw.println(); 90 iw.println("NewProxyConnection proxyCon;"); 91 iw.println(); 92 iw.print( CodegenUtils.fqcnLastElement( genclass ) ); 93 iw.println("( " + CodegenUtils.simpleClassName( intfcl ) + " inner, NewPooledConnection parentPooledConnection, NewProxyConnection proxyCon )"); 94 iw.println("{"); 95 iw.upIndent(); 96 iw.println("this( inner, parentPooledConnection );"); 97 iw.println("this.proxyCon = proxyCon;"); 98 iw.downIndent(); 99 iw.println("}"); 100 } 101 } 102 103 static final class NewProxyResultSetGenerator extends JdbcProxyGenerator 104 { 105 String getInnerTypeName() 106 { return "ResultSet"; } 107 108 protected void generateDelegateCode( Class intfcl, String genclass, Method method, IndentedWriter iw ) throws IOException 109 { 110 iw.println("if (proxyConn != null) proxyConn.maybeDirtyTransaction();"); 111 iw.println(); 112 String mname = method.getName(); 113 Class retType = method.getReturnType(); 114 115 if ( mname.equals("close") ) 116 { 117 iw.println("if (! this.isDetached())"); 118 iw.println("{"); 119 iw.upIndent(); 120 121 iw.println("if (creator instanceof Statement)"); 122 iw.upIndent(); 123 iw.println("parentPooledConnection.markInactiveResultSetForStatement( (Statement) creator, inner );"); 124 iw.downIndent(); 125 iw.println("else if (creator instanceof DatabaseMetaData)"); 126 iw.upIndent(); 127 iw.println("parentPooledConnection.markInactiveMetaDataResultSet( inner );"); 128 iw.downIndent(); 129 iw.println("else if (creator instanceof Connection)"); 130 iw.upIndent(); 131 iw.println("parentPooledConnection.markInactiveRawConnectionResultSet( inner );"); 132 iw.downIndent(); 133 iw.println("else throw new InternalError(\042Must be Statement or DatabaseMetaData -- Bad Creator: \042 + creator);"); 134 135 iw.println("this.detach();"); 136 iw.println("inner.close();"); 137 iw.println("this.inner = null;"); 138 139 iw.downIndent(); 140 iw.println("}"); 141 } 142 else if ( mname.equals("getStatement") ) 143 { 144 iw.println("if (creator instanceof Statement)"); 145 iw.upIndent(); 146 iw.println("return (Statement) creatorProxy;"); 147 iw.downIndent(); 148 iw.println("else if (creator instanceof DatabaseMetaData)"); 149 iw.upIndent(); 150 iw.println("return null;"); 151 iw.downIndent(); 152 iw.println("else throw new InternalError(\042Must be Statement or DatabaseMetaData -- Bad Creator: \042 + creator);"); 153 } 154 else if ( mname.equals("isClosed") ) 155 { 156 iw.println( "return this.isDetached();" ); 157 } 158 else 159 super.generateDelegateCode( intfcl, genclass, method, iw ); 160 } 161 162 protected void generateExtraDeclarations( Class intfcl, String genclass, IndentedWriter iw ) throws IOException 163 { 164 super.generateExtraDeclarations( intfcl, genclass, iw ); 165 iw.println(); 166 iw.println("Object creator;"); 167 iw.println("Object creatorProxy;"); 168 iw.println("NewProxyConnection proxyConn;"); 169 iw.println(); 170 iw.print( CodegenUtils.fqcnLastElement( genclass ) ); 171 iw.println("( " + CodegenUtils.simpleClassName( intfcl ) + " inner, NewPooledConnection parentPooledConnection, Object c, Object cProxy )"); 172 iw.println("{"); 173 iw.upIndent(); 174 iw.println("this( inner, parentPooledConnection );"); 175 iw.println("this.creator = c;"); 176 iw.println("this.creatorProxy = cProxy;"); 177 iw.println("if (creatorProxy instanceof NewProxyConnection) this.proxyConn = (NewProxyConnection) cProxy;"); 178 iw.downIndent(); 179 iw.println("}"); 180 } 181 182 protected void generatePreDelegateCode( Class intfcl, String genclass, Method method, IndentedWriter iw ) throws IOException 183 { 184 super.generatePreDelegateCode( intfcl, genclass, method, iw ); 185 } 186 } 187 188 static final class NewProxyAnyStatementGenerator extends JdbcProxyGenerator 189 { 190 String getInnerTypeName() 191 { return "Statement"; } 192 193 private final static boolean CONCURRENT_ACCESS_DEBUG = false; 194 195 { 196 this.setExtraInterfaces( new Class [] { C3P0ProxyStatement.class } ); 197 } 198 199 protected void generateDelegateCode( Class intfcl, String genclass, Method method, IndentedWriter iw ) throws IOException 200 { 201 iw.println("maybeDirtyTransaction();"); 202 iw.println(); 203 204 String mname = method.getName(); 205 Class retType = method.getReturnType(); 206 207 if ( ResultSet.class.isAssignableFrom( retType ) ) 208 { 209 iw.println("ResultSet innerResultSet = inner." + CodegenUtils.methodCall( method ) + ";"); 210 iw.println("if (innerResultSet == null) return null;"); 211 iw.println("parentPooledConnection.markActiveResultSetForStatement( inner, innerResultSet );"); 212 iw.println("return new NewProxyResultSet( innerResultSet, parentPooledConnection, inner, this );"); 213 } 214 else if ( mname.equals("getConnection") ) 215 { 216 iw.println("if (! this.isDetached())"); 217 iw.upIndent(); 218 iw.println("return creatorProxy;"); 219 iw.downIndent(); 220 iw.println("else"); 221 iw.upIndent(); 222 iw.println("throw new SQLException(\"You cannot operate on a closed Statement!\");"); 223 iw.downIndent(); 224 } 225 else if ( mname.equals("close") ) 226 { 227 iw.println("if (! this.isDetached())"); 228 iw.println("{"); 229 iw.upIndent(); 230 231 iw.println("if ( is_cached )"); 232 iw.upIndent(); 233 iw.println("parentPooledConnection.checkinStatement( inner );"); 234 iw.downIndent(); 235 iw.println("else"); 236 iw.println("{"); 237 iw.upIndent(); 238 iw.println("parentPooledConnection.markInactiveUncachedStatement( inner );"); 239 240 iw.println("try{ inner.close(); }"); 241 iw.println("catch (Exception e )"); 242 iw.println("{"); 243 iw.upIndent(); 244 245 iw.println("if (logger.isLoggable( MLevel.WARNING ))"); 246 iw.upIndent(); 247 iw.println("logger.log( MLevel.WARNING, \042Exception on close of inner statement.\042, e);"); 248 iw.downIndent(); 249 250 iw.println( "SQLException sqle = SqlUtils.toSQLException( e );" ); 251 iw.println( "throw sqle;" ); 252 iw.downIndent(); 253 iw.println("}"); 254 iw.downIndent(); 255 iw.println("}"); 256 257 iw.println(); 258 iw.println("this.detach();"); 259 iw.println("this.inner = null;"); 260 iw.println("this.creatorProxy = null;"); 261 262 iw.downIndent(); 263 iw.println("}"); 264 } 265 else if ( mname.equals("isClosed") ) 266 { 267 iw.println( "return this.isDetached();" ); 268 } 269 else 270 super.generateDelegateCode( intfcl, genclass, method, iw ); 271 } 272 273 protected void generatePreDelegateCode( Class intfcl, String genclass, Method method, IndentedWriter iw ) throws IOException 274 { 275 if (CONCURRENT_ACCESS_DEBUG) 277 { 278 iw.println("Object record;"); 279 iw.println("synchronized (concurrentAccessRecorder)"); 280 iw.println("{"); 281 iw.upIndent(); 282 283 iw.println("record = concurrentAccessRecorder.record();"); 284 iw.println("int num_concurrent_clients = concurrentAccessRecorder.size();"); 285 iw.println("if (num_concurrent_clients != 1)"); 286 iw.upIndent(); 287 iw.println("logger.log(MLevel.WARNING, " + 288 "concurrentAccessRecorder.getDump(\042Apparent concurrent access! (\042 + num_concurrent_clients + \042 clients.\042) );"); 289 iw.downIndent(); 290 iw.downIndent(); 291 iw.println("}"); 292 iw.println(); 293 } 294 296 super.generatePreDelegateCode( intfcl, genclass, method, iw ); 297 } 298 299 protected void generatePostDelegateCode( Class intfcl, String genclass, Method method, IndentedWriter iw ) throws IOException 300 { 301 super.generatePostDelegateCode( intfcl, genclass, method, iw ); 302 303 if (CONCURRENT_ACCESS_DEBUG) 305 { 306 iw.println("finally"); 307 iw.println("{"); 308 iw.upIndent(); 309 iw.println("concurrentAccessRecorder.remove( record );"); 310 iw.downIndent(); 311 iw.println("}"); 312 } 313 } 315 316 protected void generateExtraDeclarations( Class intfcl, String genclass, IndentedWriter iw ) throws IOException 317 { 318 super.generateExtraDeclarations( intfcl, genclass, iw ); 319 iw.println(); 320 321 if (CONCURRENT_ACCESS_DEBUG) 323 { 324 iw.println("com.mchange.v2.debug.ThreadNameStackTraceRecorder concurrentAccessRecorder"); 325 iw.upIndent(); 326 iw.println("= new com.mchange.v2.debug.ThreadNameStackTraceRecorder(\042Concurrent Access Recorder\042);"); 327 iw.downIndent(); 328 } 329 331 iw.println("boolean is_cached;"); 332 iw.println("NewProxyConnection creatorProxy;"); 333 iw.println(); 334 iw.print( CodegenUtils.fqcnLastElement( genclass ) ); 335 iw.println("( " + CodegenUtils.simpleClassName( intfcl ) + 336 " inner, NewPooledConnection parentPooledConnection, boolean cached, NewProxyConnection cProxy )"); 337 iw.println("{"); 338 iw.upIndent(); 339 iw.println("this( inner, parentPooledConnection );"); 340 iw.println("this.is_cached = cached;"); 341 iw.println("this.creatorProxy = cProxy;"); 342 iw.downIndent(); 343 iw.println("}"); 344 iw.println(); 345 iw.println("public Object rawStatementOperation(Method m, Object target, Object[] args) " + 346 "throws IllegalAccessException, InvocationTargetException, SQLException"); 347 iw.println("{"); 348 iw.upIndent(); 349 iw.println("maybeDirtyTransaction();"); 350 iw.println(); 351 iw.println("if (target == C3P0ProxyStatement.RAW_STATEMENT) target = inner;"); 352 iw.println("for (int i = 0, len = args.length; i < len; ++i)"); 353 iw.upIndent(); 354 iw.println("if (args[i] == C3P0ProxyStatement.RAW_STATEMENT) args[i] = inner;"); 355 iw.downIndent(); 356 iw.println("Object out = m.invoke(target, args);"); 357 iw.println("if (out instanceof ResultSet)"); 358 iw.println("{"); 359 iw.upIndent(); 360 iw.println("ResultSet innerResultSet = (ResultSet) out;"); 361 iw.println("parentPooledConnection.markActiveResultSetForStatement( inner, innerResultSet );"); 362 iw.println("out = new NewProxyResultSet( innerResultSet, parentPooledConnection, inner, this );"); 363 iw.downIndent(); 364 iw.println("}"); 365 iw.println(); 366 iw.println("return out;"); 367 iw.downIndent(); 368 iw.println("}"); 369 iw.println(); 370 iw.println("void maybeDirtyTransaction()"); 371 iw.println("{ creatorProxy.maybeDirtyTransaction(); }"); 372 } 373 374 protected void generateExtraImports( IndentedWriter iw ) throws IOException 375 { 376 super.generateExtraImports( iw ); 377 iw.println("import java.lang.reflect.InvocationTargetException;"); 378 } 379 380 381 } 382 383 399 static final class NewProxyConnectionGenerator extends JdbcProxyGenerator 400 { 401 String getInnerTypeName() 402 { return "Connection"; } 403 404 { 405 this.setMethodModifiers( Modifier.PUBLIC | Modifier.SYNCHRONIZED ); 406 this.setExtraInterfaces( new Class [] { C3P0ProxyConnection.class } ); 407 } 408 409 protected void generateDelegateCode( Class intfcl, String genclass, Method method, IndentedWriter iw ) throws IOException 410 { 411 String mname = method.getName(); 412 if (mname.equals("createStatement")) 413 { 414 iw.println("txn_known_resolved = false;"); 415 iw.println(); 416 iw.println("Statement innerStmt = inner." + CodegenUtils.methodCall( method ) + ";"); 417 iw.println("parentPooledConnection.markActiveUncachedStatement( innerStmt );"); 418 iw.println("return new NewProxyStatement( innerStmt, parentPooledConnection, false, this );"); 419 } 420 else if (mname.equals("prepareStatement")) 421 { 422 iw.println("txn_known_resolved = false;"); 423 iw.println(); 424 iw.println("PreparedStatement innerStmt;"); 425 iw.println(); 426 iw.println("if ( parentPooledConnection.isStatementCaching() )"); 427 iw.println("{"); 428 iw.upIndent(); 429 430 iw.println("try"); 431 iw.println("{"); 432 iw.upIndent(); 433 434 generateFindMethodAndArgs( method, iw ); 435 iw.println("innerStmt = (PreparedStatement) parentPooledConnection.checkoutStatement( method, args );"); 436 iw.println("return new NewProxyPreparedStatement( innerStmt, parentPooledConnection, true, this );"); 437 438 iw.downIndent(); 439 iw.println("}"); 440 iw.println("catch (ResourceClosedException e)"); 441 iw.println("{"); 442 iw.upIndent(); 443 444 iw.println("if ( logger.isLoggable( MLevel.FINE ) )"); 445 iw.upIndent(); 446 iw.println("logger.log( MLevel.FINE, " + 447 "\042A Connection tried to prepare a Statement via a Statement cache that is already closed. " + 448 "This can happen -- rarely -- if a DataSource is closed or reset() while Connections are checked-out and in use.\042, e );"); 449 iw.downIndent(); 450 451 iw.println("innerStmt = inner." + CodegenUtils.methodCall( method ) + ";"); 453 iw.println("parentPooledConnection.markActiveUncachedStatement( innerStmt );"); 454 iw.println("return new NewProxyPreparedStatement( innerStmt, parentPooledConnection, false, this );"); 455 456 iw.downIndent(); 457 iw.println("}"); 458 459 iw.downIndent(); 460 iw.println("}"); 461 iw.println("else"); 462 iw.println("{"); 463 iw.upIndent(); 464 465 iw.println("innerStmt = inner." + CodegenUtils.methodCall( method ) + ";"); 467 iw.println("parentPooledConnection.markActiveUncachedStatement( innerStmt );"); 468 iw.println("return new NewProxyPreparedStatement( innerStmt, parentPooledConnection, false, this );"); 469 470 iw.downIndent(); 471 iw.println("}"); 472 473 } 474 else if (mname.equals("prepareCall")) 475 { 476 iw.println("txn_known_resolved = false;"); 477 iw.println(); 478 iw.println("CallableStatement innerStmt;"); 479 iw.println(); 480 iw.println("if ( parentPooledConnection.isStatementCaching() )"); 481 iw.println("{"); 482 iw.upIndent(); 483 484 iw.println("try"); 485 iw.println("{"); 486 iw.upIndent(); 487 488 generateFindMethodAndArgs( method, iw ); 489 iw.println("innerStmt = (CallableStatement) parentPooledConnection.checkoutStatement( method, args );"); 490 iw.println("return new NewProxyCallableStatement( innerStmt, parentPooledConnection, true, this );"); 491 492 iw.downIndent(); 493 iw.println("}"); 494 iw.println("catch (ResourceClosedException e)"); 495 iw.println("{"); 496 iw.upIndent(); 497 498 iw.println("if ( logger.isLoggable( MLevel.FINE ) )"); 499 iw.upIndent(); 500 iw.println("logger.log( MLevel.FINE, " + 501 "\042A Connection tried to prepare a CallableStatement via a Statement cache that is already closed. " + 502 "This can happen -- rarely -- if a DataSource is closed or reset() while Connections are checked-out and in use.\042, e );"); 503 iw.downIndent(); 504 505 iw.println("innerStmt = inner." + CodegenUtils.methodCall( method ) + ";"); 507 iw.println("parentPooledConnection.markActiveUncachedStatement( innerStmt );"); 508 iw.println("return new NewProxyCallableStatement( innerStmt, parentPooledConnection, false, this );"); 509 510 iw.downIndent(); 511 iw.println("}"); 512 513 iw.downIndent(); 514 iw.println("}"); 515 iw.println("else"); 516 iw.println("{"); 517 iw.upIndent(); 518 519 iw.println("innerStmt = inner." + CodegenUtils.methodCall( method ) + ";"); 521 iw.println("parentPooledConnection.markActiveUncachedStatement( innerStmt );"); 522 iw.println("return new NewProxyCallableStatement( innerStmt, parentPooledConnection, false, this );"); 523 524 iw.downIndent(); 525 iw.println("}"); 526 527 } 528 else if (mname.equals("getMetaData")) 529 { 530 iw.println("txn_known_resolved = false;"); 531 iw.println(); 532 iw.println("if (this.metaData == null)"); 533 iw.println("{"); 534 iw.upIndent(); 535 iw.println("DatabaseMetaData innerMetaData = inner." + CodegenUtils.methodCall( method ) + ";"); 536 iw.println("this.metaData = new NewProxyDatabaseMetaData( innerMetaData, parentPooledConnection, this );"); 537 iw.downIndent(); 538 iw.println("}"); 539 iw.println("return this.metaData;"); 540 } 541 else if ( mname.equals("setTransactionIsolation") ) 542 { 543 545 super.generateDelegateCode( intfcl, genclass, method, iw ); 546 iw.println( "parentPooledConnection.markNewTxnIsolation( " + CodegenUtils.generatedArgumentName( 0 ) + " );"); 547 } 548 else if ( mname.equals("setCatalog") ) 549 { 550 552 super.generateDelegateCode( intfcl, genclass, method, iw ); 553 iw.println( "parentPooledConnection.markNewCatalog( " + CodegenUtils.generatedArgumentName( 0 ) + " );"); 554 } 555 else if ( mname.equals("setHoldability") ) 556 { 557 559 super.generateDelegateCode( intfcl, genclass, method, iw ); 560 iw.println( "parentPooledConnection.markNewHoldability( " + CodegenUtils.generatedArgumentName( 0 ) + " );"); 561 } 562 else if ( mname.equals("setReadOnly") ) 563 { 564 566 super.generateDelegateCode( intfcl, genclass, method, iw ); 567 iw.println( "parentPooledConnection.markNewReadOnly( " + CodegenUtils.generatedArgumentName( 0 ) + " );"); 568 } 569 else if ( mname.equals("setTypeMap") ) 570 { 571 573 super.generateDelegateCode( intfcl, genclass, method, iw ); 574 iw.println( "parentPooledConnection.markNewTypeMap( " + CodegenUtils.generatedArgumentName( 0 ) + " );"); 575 } 576 else if ( mname.equals("close") ) 577 { 578 iw.println("if (! this.isDetached())"); 579 iw.println("{"); 580 iw.upIndent(); 581 iw.println("NewPooledConnection npc = parentPooledConnection;"); 582 iw.println("this.detach();"); 583 iw.println("npc.markClosedProxyConnection( this, txn_known_resolved );"); 584 iw.println("this.inner = null;"); 585 iw.downIndent(); 586 iw.println("}"); 587 iw.println("else if (Debug.DEBUG && logger.isLoggable( MLevel.FINE ))"); 588 iw.println("{"); 589 iw.upIndent(); 590 iw.println("logger.log( MLevel.FINE, this + \042: close() called more than once.\042 );"); 591 592 if (PREMATURE_DETACH_DEBUG) 594 { 595 iw.println("prematureDetachRecorder.record();"); 596 iw.println("logger.warning( prematureDetachRecorder.getDump(\042Apparent multiple close of " + 597 getInnerTypeName() + ".\042) );"); 598 } 599 601 iw.downIndent(); 602 iw.println("}"); 603 } 604 else if ( mname.equals("isClosed") ) 605 { 606 iw.println("return this.isDetached();"); 607 } 608 else 609 { 610 iw.println("txn_known_resolved = " + 611 ( mname.equals("commit") || mname.equals( "rollback" ) || mname.equals( "setAutoCommit" ) ) + 612 ';'); 613 iw.println(); 614 super.generateDelegateCode( intfcl, genclass, method, iw ); 615 } 616 } 617 618 protected void generateExtraDeclarations( Class intfcl, String genclass, IndentedWriter iw ) throws IOException 619 { 620 iw.println("boolean txn_known_resolved = true;"); 621 iw.println(); 622 iw.println("DatabaseMetaData metaData = null;"); 623 iw.println(); 624 625 627 639 iw.println("public Object rawConnectionOperation(Method m, Object target, Object[] args)"); 640 iw.upIndent(); 641 iw.println("throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, SQLException"); 642 iw.downIndent(); 643 iw.println("{"); 644 iw.upIndent(); 645 iw.println("maybeDirtyTransaction();"); 646 iw.println(); 647 iw.println("if (inner == null)"); 648 iw.upIndent(); 649 iw.println("throw new SQLException(\"You cannot operate on a closed Connection!\");"); 650 iw.downIndent(); 651 652 iw.println("if ( target == C3P0ProxyConnection.RAW_CONNECTION)"); 653 iw.upIndent(); 654 iw.println("target = inner;"); 655 iw.downIndent(); 656 657 iw.println("for (int i = 0, len = args.length; i < len; ++i)"); 658 iw.upIndent(); 659 iw.println("if (args[i] == C3P0ProxyConnection.RAW_CONNECTION)"); 660 iw.upIndent(); 661 iw.println("args[i] = inner;"); 662 iw.downIndent(); 663 iw.downIndent(); 664 665 iw.println("Object out = m.invoke( target, args );"); 666 iw.println(); 667 iw.println("// we never cache Statements generated by an operation on the raw Connection"); 668 iw.println("if (out instanceof CallableStatement)"); 669 iw.println("{"); 670 iw.upIndent(); 671 iw.println("CallableStatement innerStmt = (CallableStatement) out;"); 672 iw.println("parentPooledConnection.markActiveUncachedStatement( innerStmt );"); 673 iw.println("out = new NewProxyCallableStatement( innerStmt, parentPooledConnection, false, this );"); 674 iw.downIndent(); 675 iw.println("}"); 676 iw.println("else if (out instanceof PreparedStatement)"); 677 iw.println("{"); 678 iw.upIndent(); 679 iw.println("PreparedStatement innerStmt = (PreparedStatement) out;"); 680 iw.println("parentPooledConnection.markActiveUncachedStatement( innerStmt );"); 681 iw.println("out = new NewProxyPreparedStatement( innerStmt, parentPooledConnection, false, this );"); 682 iw.downIndent(); 683 iw.println("}"); 684 iw.println("else if (out instanceof Statement)"); 685 iw.println("{"); 686 iw.upIndent(); 687 iw.println("Statement innerStmt = (Statement) out;"); 688 iw.println("parentPooledConnection.markActiveUncachedStatement( innerStmt );"); 689 iw.println("out = new NewProxyStatement( innerStmt, parentPooledConnection, false, this );"); 690 iw.downIndent(); 691 iw.println("}"); 692 iw.println("else if (out instanceof ResultSet)"); 693 iw.println("{"); 694 iw.upIndent(); 695 iw.println("ResultSet innerRs = (ResultSet) out;"); 696 iw.println("parentPooledConnection.markActiveRawConnectionResultSet( innerRs );"); 697 iw.println("out = new NewProxyResultSet( innerRs, parentPooledConnection, inner, this );"); 698 iw.downIndent(); 699 iw.println("}"); 700 iw.println("else if (out instanceof DatabaseMetaData)"); 701 iw.upIndent(); 702 iw.println("out = new NewProxyDatabaseMetaData( (DatabaseMetaData) out, parentPooledConnection );"); 703 iw.downIndent(); 704 iw.println("return out;"); 705 iw.downIndent(); 706 iw.println("}"); 707 iw.println(); 708 iw.println("synchronized void maybeDirtyTransaction()"); 709 iw.println("{ txn_known_resolved = false; }"); 710 711 super.generateExtraDeclarations( intfcl, genclass, iw ); 712 } 713 714 void generateFindMethodAndArgs( Method method, IndentedWriter iw ) throws IOException 715 { 716 iw.println("Class[] argTypes = "); 717 iw.println("{"); 718 iw.upIndent(); 719 720 Class [] argTypes = method.getParameterTypes(); 721 for (int i = 0, len = argTypes.length; i < len; ++i) 722 { 723 if (i != 0) iw.println(","); 724 iw.print( CodegenUtils.simpleClassName( argTypes[i] ) + ".class" ); 725 } 726 iw.println(); 727 iw.downIndent(); 728 iw.println("};"); 729 iw.println("Method method = Connection.class.getMethod( \042" + method.getName() + "\042 , argTypes );"); 730 iw.println(); 731 iw.println("Object[] args = "); 732 iw.println("{"); 733 iw.upIndent(); 734 735 for (int i = 0, len = argTypes.length; i < len; ++i) 736 { 737 if (i != 0) iw.println(","); 738 String argName = CodegenUtils.generatedArgumentName( i ); 739 Class argType = argTypes[i]; 740 if (argType.isPrimitive()) 741 { 742 if (argType == boolean.class) 743 iw.print( "Boolean.valueOf( " + argName + " )" ); 744 else if (argType == byte.class) 745 iw.print( "new Byte( " + argName + " )" ); 746 else if (argType == char.class) 747 iw.print( "new Character( " + argName + " )" ); 748 else if (argType == short.class) 749 iw.print( "new Short( " + argName + " )" ); 750 else if (argType == int.class) 751 iw.print( "new Integer( " + argName + " )" ); 752 else if (argType == long.class) 753 iw.print( "new Long( " + argName + " )" ); 754 else if (argType == float.class) 755 iw.print( "new Float( " + argName + " )" ); 756 else if (argType == double.class) 757 iw.print( "new Double( " + argName + " )" ); 758 } 759 else 760 iw.print( argName ); 761 } 762 763 iw.downIndent(); 764 iw.println("};"); 765 } 766 767 protected void generateExtraImports( IndentedWriter iw ) throws IOException 768 { 769 super.generateExtraImports( iw ); 770 iw.println("import java.lang.reflect.InvocationTargetException;"); 771 iw.println("import com.mchange.v2.util.ResourceClosedException;"); 772 } 773 } 774 775 protected void generatePreDelegateCode( Class intfcl, String genclass, Method method, IndentedWriter iw ) throws IOException 776 { 777 generateTryOpener( iw ); 778 } 779 780 protected void generatePostDelegateCode( Class intfcl, String genclass, Method method, IndentedWriter iw ) throws IOException 781 { 782 generateTryCloserAndCatch( intfcl, genclass, method, iw ); 783 } 784 785 void generateTryOpener( IndentedWriter iw ) throws IOException 786 { 787 iw.println("try"); 788 iw.println("{"); 789 iw.upIndent(); 790 } 791 792 void generateTryCloserAndCatch( Class intfcl, String genclass, Method method, IndentedWriter iw ) throws IOException 793 { 794 iw.downIndent(); 795 iw.println("}"); 796 iw.println("catch (NullPointerException exc)"); 797 iw.println("{"); 798 iw.upIndent(); 799 iw.println("if ( this.isDetached() )"); 800 iw.println("{"); 801 iw.upIndent(); 802 if ( "close".equals( method.getName() ) ) 805 { 806 iw.println("if (Debug.DEBUG && logger.isLoggable( MLevel.FINE ))"); 807 iw.println("{"); 808 iw.upIndent(); 809 iw.println("logger.log( MLevel.FINE, this + \042: close() called more than once.\042 );"); 810 811 if (PREMATURE_DETACH_DEBUG) 813 { 814 iw.println("prematureDetachRecorder.record();"); 815 iw.println("logger.warning( prematureDetachRecorder.getDump(\042Apparent multiple close of " + 816 getInnerTypeName() + ".\042) );"); 817 } 818 820 iw.downIndent(); 821 iw.println("}"); 822 } 823 else 824 { 825 if (PREMATURE_DETACH_DEBUG) 827 { 828 iw.println("prematureDetachRecorder.record();"); 829 iw.println("logger.warning( prematureDetachRecorder.getDump(\042Use of already detached " + 830 getInnerTypeName() + ".\042) );"); 831 } 832 834 iw.println( "throw SqlUtils.toSQLException(\042You can't operate on a closed " + getInnerTypeName() + "!!!\042, exc);"); 835 } 836 iw.downIndent(); 837 iw.println("}"); 838 iw.println( "else throw exc;" ); 839 iw.downIndent(); 840 iw.println("}"); 841 iw.println("catch (Exception exc)"); 842 iw.println("{"); 843 iw.upIndent(); 844 iw.println("if (! this.isDetached())"); 845 iw.println("{"); 846 iw.upIndent(); 847 iw.println( "throw parentPooledConnection.handleThrowable( exc );" ); 849 iw.downIndent(); 850 iw.println("}"); 851 iw.println("else throw SqlUtils.toSQLException( exc );"); 852 iw.downIndent(); 853 iw.println("}"); 854 } 855 856 protected void generateExtraDeclarations( Class intfcl, String genclass, IndentedWriter iw ) throws IOException 857 { 858 if (PREMATURE_DETACH_DEBUG) 860 { 861 iw.println("com.mchange.v2.debug.ThreadNameStackTraceRecorder prematureDetachRecorder"); 862 iw.upIndent(); 863 iw.println("= new com.mchange.v2.debug.ThreadNameStackTraceRecorder(\042Premature Detach Recorder\042);"); 864 iw.downIndent(); 865 } 866 868 iw.println("private final static MLogger logger = MLog.getLogger( \042" + genclass + "\042 );"); 869 iw.println(); 870 871 iw.println("volatile NewPooledConnection parentPooledConnection;"); 872 iw.println(); 873 874 iw.println("ConnectionEventListener cel = new ConnectionEventListener()"); 875 iw.println("{"); 876 iw.upIndent(); 877 878 iw.println("public void connectionErrorOccurred(ConnectionEvent evt)"); 879 iw.println("{ /* DON'T detach()... IGNORE -- this could be an ordinary error. Leave it to the PooledConnection to test, but leave proxies intact */ }"); 880 882 iw.println(); 883 iw.println("public void connectionClosed(ConnectionEvent evt)"); 884 iw.println("{ detach(); }"); 885 886 iw.downIndent(); 887 iw.println("};"); 888 iw.println(); 889 890 iw.println("void attach( NewPooledConnection parentPooledConnection )"); 891 iw.println("{"); 892 iw.upIndent(); 893 iw.println("this.parentPooledConnection = parentPooledConnection;"); 894 iw.println("parentPooledConnection.addConnectionEventListener( cel );"); 895 iw.downIndent(); 896 iw.println("}"); 897 iw.println(); 898 iw.println("private void detach()"); 899 iw.println("{"); 900 iw.upIndent(); 901 902 writeDetachBody(iw); 904 905 iw.downIndent(); 906 iw.println("}"); 907 iw.println(); 908 iw.print( CodegenUtils.fqcnLastElement( genclass ) ); 909 iw.println("( " + CodegenUtils.simpleClassName( intfcl ) + " inner, NewPooledConnection parentPooledConnection )"); 910 iw.println("{"); 911 iw.upIndent(); 912 iw.println("this( inner );"); 913 iw.println("attach( parentPooledConnection );"); 914 generateExtraConstructorCode( intfcl, genclass, iw ); 915 iw.downIndent(); 916 iw.println("}"); 917 iw.println(); 918 iw.println("boolean isDetached()"); 919 iw.println("{ return (this.parentPooledConnection == null); }"); 920 } 921 922 protected void writeDetachBody(IndentedWriter iw) throws IOException 923 { 924 if (PREMATURE_DETACH_DEBUG) 926 { 927 iw.println("prematureDetachRecorder.record();"); 928 iw.println("if (this.isDetached())"); 929 iw.upIndent(); 930 iw.println("logger.warning( prematureDetachRecorder.getDump(\042Double Detach.\042) );"); 931 iw.downIndent(); 932 } 933 935 iw.println("parentPooledConnection.removeConnectionEventListener( cel );"); 936 iw.println("parentPooledConnection = null;"); 937 } 938 939 protected void generateExtraImports( IndentedWriter iw ) throws IOException 940 { 941 iw.println("import java.sql.*;"); 942 iw.println("import javax.sql.*;"); 943 iw.println("import com.mchange.v2.log.*;"); 944 iw.println("import java.lang.reflect.Method;"); 945 iw.println("import com.mchange.v2.sql.SqlUtils;"); 946 } 947 948 void generateExtraConstructorCode( Class intfcl, String genclass, IndentedWriter iw ) throws IOException 949 {} 950 951 public static void main( String [] argv ) 952 { 953 try 954 { 955 if (argv.length != 1) 956 { 957 System.err.println("java " + JdbcProxyGenerator.class.getName() + " <source-root-directory>"); 958 return; 959 } 960 961 File srcroot = new File( argv[0] ); 962 if (! srcroot.exists() || !srcroot.canWrite() ) 963 { 964 System.err.println(JdbcProxyGenerator.class.getName() + " -- sourceroot: " + argv[0] + " must exist and be writable"); 965 return; 966 } 967 968 DelegatorGenerator mdgen = new NewProxyMetaDataGenerator(); 969 DelegatorGenerator rsgen = new NewProxyResultSetGenerator(); 970 DelegatorGenerator stgen = new NewProxyAnyStatementGenerator(); 971 DelegatorGenerator cngen = new NewProxyConnectionGenerator(); 972 973 genclass( cngen, Connection.class, "com.mchange.v2.c3p0.impl.NewProxyConnection", srcroot ); 974 genclass( stgen, Statement.class, "com.mchange.v2.c3p0.impl.NewProxyStatement", srcroot ); 975 genclass( stgen, PreparedStatement.class, "com.mchange.v2.c3p0.impl.NewProxyPreparedStatement", srcroot ); 976 genclass( stgen, CallableStatement.class, "com.mchange.v2.c3p0.impl.NewProxyCallableStatement", srcroot ); 977 genclass( rsgen, ResultSet.class, "com.mchange.v2.c3p0.impl.NewProxyResultSet", srcroot ); 978 genclass( mdgen, DatabaseMetaData.class, "com.mchange.v2.c3p0.impl.NewProxyDatabaseMetaData", srcroot ); 979 } 980 catch ( Exception e ) 981 { e.printStackTrace(); } 982 } 983 984 static void genclass( DelegatorGenerator dg, Class intfcl, String fqcn, File srcroot ) throws IOException 985 { 986 File genDir = new File( srcroot, dirForFqcn( fqcn ) ); 987 if (! genDir.exists() ) 988 { 989 System.err.println( JdbcProxyGenerator.class.getName() + " -- creating directory: " + genDir.getAbsolutePath() ); 990 genDir.mkdirs(); 991 } 992 String fileName = CodegenUtils.fqcnLastElement( fqcn ) + ".java"; 993 Writer w = null; 994 try 995 { 996 w = new BufferedWriter( new FileWriter( new File( genDir, fileName ) ) ); 997 dg.writeDelegator( intfcl, fqcn, w ); 998 w.flush(); 999 System.err.println("Generated " + fileName); 1000 } 1001 finally 1002 { 1003 try { if (w != null) w.close(); } 1004 catch ( Exception e ) 1005 { e.printStackTrace(); } 1006 } 1007 } 1008 1009 static String dirForFqcn( String fqcn ) 1010 { 1011 int last_dot = fqcn.lastIndexOf('.'); 1012 StringBuffer sb = new StringBuffer ( fqcn.substring( 0, last_dot + 1) ); 1013 for (int i = 0, len = sb.length(); i < len; ++i) 1014 if (sb.charAt(i) == '.') 1015 sb.setCharAt(i, '/'); 1016 return sb.toString(); 1017 } 1018} 1019 | Popular Tags |