KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mchange > v2 > c3p0 > codegen > JdbcProxyGenerator


1 /*
2  * Distributed as part of c3p0 v.0.9.1
3  *
4  * Copyright (C) 2005 Machinery For Change, Inc.
5  *
6  * Author: Steve Waldman <swaldman@mchange.com>
7  *
8  * This library is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License version 2.1, as
10  * published by the Free Software Foundation.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this software; see the file LICENSE. If not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */

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 JavaDoc getInnerTypeName();
49
50     static final class NewProxyMetaDataGenerator extends JdbcProxyGenerator
51     {
52         String JavaDoc getInnerTypeName()
53         { return "DatabaseMetaData"; }
54
55         protected void generateDelegateCode( Class JavaDoc intfcl, String JavaDoc genclass, Method method, IndentedWriter iw ) throws IOException
56         {
57             String JavaDoc mname = method.getName();
58             Class JavaDoc 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 JavaDoc intfcl, String JavaDoc 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 JavaDoc intfcl, String JavaDoc 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 JavaDoc intfcl, String JavaDoc 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 JavaDoc getInnerTypeName()
106         { return "ResultSet"; }
107
108         protected void generateDelegateCode( Class JavaDoc intfcl, String JavaDoc genclass, Method method, IndentedWriter iw ) throws IOException
109         {
110             iw.println("if (proxyConn != null) proxyConn.maybeDirtyTransaction();");
111             iw.println();
112             String JavaDoc mname = method.getName();
113             Class JavaDoc 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 JavaDoc intfcl, String JavaDoc 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 JavaDoc intfcl, String JavaDoc 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 JavaDoc getInnerTypeName()
191         { return "Statement"; }
192
193         private final static boolean CONCURRENT_ACCESS_DEBUG = false;
194
195         {
196             this.setExtraInterfaces( new Class JavaDoc[] { C3P0ProxyStatement.class } );
197         }
198
199         protected void generateDelegateCode( Class JavaDoc intfcl, String JavaDoc genclass, Method method, IndentedWriter iw ) throws IOException
200         {
201             iw.println("maybeDirtyTransaction();");
202             iw.println();
203
204             String JavaDoc mname = method.getName();
205             Class JavaDoc 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 JavaDoc intfcl, String JavaDoc genclass, Method method, IndentedWriter iw ) throws IOException
274         {
275             // concurrent-access-debug only
276
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             // end concurrent-access-debug only
295

296             super.generatePreDelegateCode( intfcl, genclass, method, iw );
297         }
298
299         protected void generatePostDelegateCode( Class JavaDoc intfcl, String JavaDoc genclass, Method method, IndentedWriter iw ) throws IOException
300         {
301             super.generatePostDelegateCode( intfcl, genclass, method, iw );
302
303             // concurrent-access-debug only
304
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             // end concurrent-access-debug only
314
}
315
316         protected void generateExtraDeclarations( Class JavaDoc intfcl, String JavaDoc genclass, IndentedWriter iw ) throws IOException
317         {
318             super.generateExtraDeclarations( intfcl, genclass, iw );
319             iw.println();
320
321             // concurrent-access-debug only!
322
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             // end concurrent-access-debug only!
330

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 // protected void generateExtraDeclarations( Class intfcl, String genclass, IndentedWriter iw ) throws IOException
384
// {
385
// super.generateExtraDeclarations( intfcl, genclass, iw );
386
// iw.println();
387
// iw.println("Statement creatingStatement;");
388
// iw.println();
389
// iw.print( CodegenUtils.fqcnLastElement( genclass ) );
390
// iw.println("( " + CodegenUtils.simpleClassName( intfcl.getClass() ) + " inner, NewPooledConnection parentPooledConnection, Statement stmt )");
391
// iw.println("{");
392
// iw.upIndent();
393
// iw.println("this( inner, parentPooledConnection );");
394
// iw.println("this.creatingStatement = stmt;");
395
// iw.downIndent();
396
// iw.println("}");
397
// }
398

399     static final class NewProxyConnectionGenerator extends JdbcProxyGenerator
400     {
401         String JavaDoc getInnerTypeName()
402         { return "Connection"; }
403
404         {
405             this.setMethodModifiers( Modifier.PUBLIC | Modifier.SYNCHRONIZED );
406             this.setExtraInterfaces( new Class JavaDoc[] { C3P0ProxyConnection.class } );
407         }
408
409         protected void generateDelegateCode( Class JavaDoc intfcl, String JavaDoc genclass, Method method, IndentedWriter iw ) throws IOException
410         {
411             String JavaDoc 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                 // repeated code... any changes probably need to be duplicated below
452
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                 // repeated code... any changes probably need to be duplicated above
466
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                 // repeated code... any changes probably need to be duplicated below
506
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                 // repeated code... any changes probably need to be duplicated above
520
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                 //do nothing with txn_known_resolved
544

545                 super.generateDelegateCode( intfcl, genclass, method, iw );
546                 iw.println( "parentPooledConnection.markNewTxnIsolation( " + CodegenUtils.generatedArgumentName( 0 ) + " );");
547             }
548             else if ( mname.equals("setCatalog") )
549             {
550                 //do nothing with txn_known_resolved
551

552                 super.generateDelegateCode( intfcl, genclass, method, iw );
553                 iw.println( "parentPooledConnection.markNewCatalog( " + CodegenUtils.generatedArgumentName( 0 ) + " );");
554             }
555             else if ( mname.equals("setHoldability") )
556             {
557                 //do nothing with txn_known_resolved
558

559                 super.generateDelegateCode( intfcl, genclass, method, iw );
560                 iw.println( "parentPooledConnection.markNewHoldability( " + CodegenUtils.generatedArgumentName( 0 ) + " );");
561             }
562             else if ( mname.equals("setReadOnly") )
563             {
564                 //do nothing with txn_known_resolved
565

566                 super.generateDelegateCode( intfcl, genclass, method, iw );
567                 iw.println( "parentPooledConnection.markNewReadOnly( " + CodegenUtils.generatedArgumentName( 0 ) + " );");
568             }
569             else if ( mname.equals("setTypeMap") )
570             {
571                 //do nothing with txn_known_resolved
572

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                 // premature-detach-debug-debug only!
593
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                 // end-premature-detach-debug-only!
600

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 JavaDoc intfcl, String JavaDoc 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 // We've nothing to do with preferredTestQuery here... the stuff below was unnecessary
626

627 // iw.println("String preferredTestQuery = null;");
628
// iw.println();
629
// iw.print( CodegenUtils.fqcnLastElement( genclass ) );
630
// iw.println("( " + CodegenUtils.simpleClassName( intfcl ) + " inner, NewPooledConnection parentPooledConnection, String preferredTestQuery )");
631
// iw.println("{");
632
// iw.upIndent();
633
// iw.println("this( inner, parentPooledConnection );");
634
// iw.println("this.preferredTestQuery = preferredTestQuery;");
635
// iw.downIndent();
636
// iw.println("}");
637
// iw.println();
638

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 JavaDoc[] 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 JavaDoc argName = CodegenUtils.generatedArgumentName( i );
739                 Class JavaDoc 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 JavaDoc intfcl, String JavaDoc genclass, Method method, IndentedWriter iw ) throws IOException
776     {
777         generateTryOpener( iw );
778     }
779
780     protected void generatePostDelegateCode( Class JavaDoc intfcl, String JavaDoc 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 JavaDoc intfcl, String JavaDoc 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         //iw.println( "System.err.print(\042probably 'cuz we're closed -- \042);" );
803
//iw.println( "exc.printStackTrace();" );
804
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             // premature-detach-debug-debug only!
812
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             // end-premature-detach-debug-only!
819

820             iw.downIndent();
821             iw.println("}");
822         }
823         else
824         {
825             // premature-detach-debug-debug only!
826
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             // end-premature-detach-debug-only!
833

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( "exc.printStackTrace();" );
848
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 JavaDoc intfcl, String JavaDoc genclass, IndentedWriter iw ) throws IOException
857     {
858         // premature-detach-debug-debug only!
859
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         // end-premature-detach-debug-only!
867

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         //BAD puppy -- iw.println("{ detach(); }");
881

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         // factored out so we could define debug versions...
903
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         // premature-detach-debug only
925
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         // end premature-detach-debug only
934

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 JavaDoc intfcl, String JavaDoc genclass, IndentedWriter iw ) throws IOException
949     {}
950
951     public static void main( String JavaDoc[] 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 JavaDoc e )
981         { e.printStackTrace(); }
982     }
983
984     static void genclass( DelegatorGenerator dg, Class JavaDoc intfcl, String JavaDoc 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 JavaDoc 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 JavaDoc e )
1005            { e.printStackTrace(); }
1006        }
1007    }
1008
1009    static String JavaDoc dirForFqcn( String JavaDoc fqcn )
1010    {
1011        int last_dot = fqcn.lastIndexOf('.');
1012        StringBuffer JavaDoc sb = new StringBuffer JavaDoc( 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