KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > cjdbc > driver > Connection


1 /**
2  * C-JDBC: Clustered JDBC.
3  * Copyright (C) 2002-2004 French National Institute For Research In Computer
4  * Science And Control (INRIA).
5  * Contact: c-jdbc@objectweb.org
6  *
7  * This library is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published by the
9  * Free Software Foundation; either version 2.1 of the License, or any later
10  * version.
11  *
12  * This library is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this library; if not, write to the Free Software Foundation,
19  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20  *
21  * Initial developer(s): Emmanuel Cecchet.
22  * Contributor(s): Julie Marguerite, Guillaume Bort, Duncan Smith, Vadim Kassin,
23  * Nicolas Modrzyk, Jaco Swart, Jean-Bernard van Zuylen
24  * Completely refactored by Marc Herbert to remove the use of Java serialization.
25  */

26
27 package org.objectweb.cjdbc.driver;
28
29 import java.io.IOException JavaDoc;
30 import java.net.Socket JavaDoc;
31 import java.sql.ResultSet JavaDoc;
32 import java.sql.SQLException JavaDoc;
33 import java.sql.SQLWarning JavaDoc;
34 import java.sql.Savepoint JavaDoc;
35 import java.util.HashMap JavaDoc;
36 import java.util.Iterator JavaDoc;
37 import java.util.Map JavaDoc;
38 import java.util.Properties JavaDoc;
39
40 import org.objectweb.cjdbc.common.exceptions.AuthenticationException;
41 import org.objectweb.cjdbc.common.exceptions.NoMoreBackendException;
42 import org.objectweb.cjdbc.common.exceptions.NoMoreControllerException;
43 import org.objectweb.cjdbc.common.exceptions.NotImplementedException;
44 import org.objectweb.cjdbc.common.exceptions.ProtocolException;
45 import org.objectweb.cjdbc.common.exceptions.driver.DriverSQLException;
46 import org.objectweb.cjdbc.common.exceptions.driver.protocol.BackendDriverException;
47 import org.objectweb.cjdbc.common.exceptions.driver.protocol.ControllerCoreException;
48 import org.objectweb.cjdbc.common.exceptions.driver.protocol.SerializableException;
49 import org.objectweb.cjdbc.common.sql.AbstractRequest;
50 import org.objectweb.cjdbc.common.sql.AbstractWriteRequest;
51 import org.objectweb.cjdbc.common.sql.SelectRequest;
52 import org.objectweb.cjdbc.common.sql.StoredProcedure;
53 import org.objectweb.cjdbc.common.sql.filters.AbstractBlobFilter;
54 import org.objectweb.cjdbc.common.stream.CJDBCInputStream;
55 import org.objectweb.cjdbc.common.stream.CJDBCOutputStream;
56 import org.objectweb.cjdbc.common.util.Constants;
57 import org.objectweb.cjdbc.driver.connectpolicy.AbstractControllerConnectPolicy;
58 import org.objectweb.cjdbc.driver.protocol.Commands;
59 import org.objectweb.cjdbc.driver.protocol.SQLDataSerialization;
60 import org.objectweb.cjdbc.driver.protocol.TypeTag;
61
62 /**
63  * This class implements the communication protocol to the Controller.
64  * <p>
65  * Connection.java was inspired from the PostgreSQL JDBC driver by Peter T.
66  * Mount.
67  *
68  * @author <a HREF="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
69  * @author <a HREF="mailto:Julie.Marguerite@inria.fr">Julie Marguerite </a>
70  * @author <a HREF="mailto:vadim@kase.kz">Vadim Kassin </a>
71  * @author <a HREF="mailto:duncan@mightybot.com">Duncan Smith </a>
72  * @author <a HREF="mailto:Nicolas.Modrzyk@inrialpes.fr">Nicolas Modrzyk </a>
73  * @author <a HREF="mailto:jaco.swart@iblocks.co.uk">Jaco Swart </a>
74  * @author <a HREF="mailto:Marc.Herbert@emicnetworks.com">Marc Herbert </a>
75  * @author <a HREF="mailto:jbvanzuylen@transwide.com">Jean-Bernard van Zuylen
76  * </a>
77  * @version 2.0
78  */

79 public class Connection implements java.sql.Connection JavaDoc
80 {
81   /** Does the controller wants SQL templates of PreparedStatements? */
82   protected boolean controllerNeedsSqlSkeleton = false;
83
84   /** Status of the connection. */
85   protected boolean isClosed = false;
86
87   protected String JavaDoc escapeChar = "\'";
88
89   /** C-JDBC controller we are connected to */
90   protected ControllerInfo controllerInfo = null;
91
92   // ConnectionClosingThread
93
/** Driver that created us. */
94   protected Driver driver = null;
95
96   /** Connection with the controller. */
97   protected Socket JavaDoc socket;
98   /** Socket input stream. */
99   protected CJDBCInputStream socketInput;
100   /** Socket output stream. */
101   protected CJDBCOutputStream socketOutput;
102
103   // used by Statement (and maybe also by some others _below_)
104
static final String JavaDoc LINE_SEPARATOR = System
105                                                                       .getProperty("line.separator");
106
107   // Member variables describing the state of the connection
108

109   /** Commit mode of the connection (<code>true</code>= automatic). */
110   protected boolean autoCommit = true;
111
112   /** Is the connection in read-only mode ? */
113   protected boolean readOnly = false;
114
115   /** Has a write request been executed in the current transaction? */
116   boolean writeExecutedInTransaction = false;
117
118   /** Default transaction isolation level if the user has not enforced one */
119   public static final int DEFAULT_TRANSACTION_ISOLATION_LEVEL = -1;
120   /** Current transaction isolation level. */
121   protected int isolationLevel = DEFAULT_TRANSACTION_ISOLATION_LEVEL;
122
123   /** transaction identifier. */
124   protected long transactionId = 0;
125
126   /** List of <code>Warnings</code> for this connection. */
127   protected SQLWarning JavaDoc firstWarning = null;
128
129   /** Meta-data of C-JDBC connections. */
130   protected DatabaseMetaData metaData = null;
131
132   /** Parsed URL to the database. */
133   private final CjdbcUrl cjdbcUrl;
134
135   /** Virtual database user used for this connection. */
136   protected String JavaDoc vdbUser = null;
137   protected String JavaDoc vdbPassword = null;
138
139   private AbstractBlobFilter blobFilter;
140   private boolean connectionPooling = true;
141
142   // Escape processing tuning
143
protected boolean escapeBackslash = true;
144   protected boolean escapeSingleQuote = true;
145
146   // Parsing Query values
147
protected boolean driverProcessed = true;
148
149   // PreparedStatement.setBoolean values
150
protected String JavaDoc preparedStatementBooleanTrue = "'1'";
151   protected String JavaDoc preparedStatementBooleanFalse = "'0'";
152
153   private boolean closeSocketOnGC = true;
154
155   /*****************************************************************************
156    * *************** * Constructor and get/set methods * ***********************
157    * ****************************************************************************
158    */

159
160   /**
161    * Creates a new <code>Connection</code> instance.
162    *
163    * @param driver calling driver
164    * @param socket connection with the controller
165    * @param in socket input stream
166    * @param out socket output stream
167    * @param cjdbcUrl C-JDBC URL of the database
168    * @param controller controller we are connected to
169    * @param userName user login
170    * @param password user password
171    * @throws AuthenticationException login error
172    * @throws IOException stream error
173    * @throws ProtocolException unexpected answer
174    */

175
176   public Connection(Driver driver, Socket JavaDoc socket, CJDBCInputStream in,
177       CJDBCOutputStream out, CjdbcUrl cjdbcUrl, ControllerInfo controller,
178       String JavaDoc userName, String JavaDoc password) throws AuthenticationException,
179       IOException JavaDoc, ProtocolException
180   {
181     this.driver = driver;
182     this.socket = socket;
183     this.socketInput = in;
184     this.socketOutput = out;
185     this.cjdbcUrl = cjdbcUrl;
186     this.controllerInfo = controller;
187     this.vdbUser = userName;
188     this.vdbPassword = password;
189
190     if (!in.readBoolean()) // failed
191
throw new AuthenticationException(in.readUTF());
192
193     this.controllerNeedsSqlSkeleton = in.readBoolean();
194     String JavaDoc sfilter = in.readUTF();
195     this.blobFilter = AbstractBlobFilter.getBlobFilterInstance(sfilter);
196
197     setUrlParametersOptionsOnConnection(cjdbcUrl);
198     if (cjdbcUrl.isDebugEnabled())
199       System.out.println("New connection:" + this.toString());
200   }
201
202   /**
203    * Set CjdbcUrl parameters options on connection.
204    *
205    * @param cjdbcUrl the C-JDBC URL to use
206    */

207   private void setUrlParametersOptionsOnConnection(CjdbcUrl cjdbcUrl)
208   {
209     HashMap JavaDoc cjdbcUrlParameters = cjdbcUrl.getParameters();
210
211     String JavaDoc booleanTrue = (String JavaDoc) cjdbcUrlParameters
212         .get(Driver.BOOLEAN_TRUE_PROPERTY);
213     if (booleanTrue != null)
214       setPreparedStatementBooleanTrue(booleanTrue);
215
216     String JavaDoc booleanFalse = (String JavaDoc) cjdbcUrlParameters
217         .get(Driver.BOOLEAN_FALSE_PROPERTY);
218     if (booleanFalse != null)
219       setPreparedStatementBooleanFalse(booleanFalse);
220
221     String JavaDoc escapeBaskslash = (String JavaDoc) cjdbcUrlParameters
222         .get(Driver.ESCAPE_BACKSLASH_PROPERTY);
223     if (escapeBaskslash != null)
224       setEscapeBackslash(new Boolean JavaDoc(escapeBaskslash).booleanValue());
225
226     String JavaDoc escapeQuote = (String JavaDoc) cjdbcUrlParameters
227         .get(Driver.ESCAPE_SINGLE_QUOTE_PROPERTY);
228     if (escapeQuote != null)
229       setEscapeSingleQuote(new Boolean JavaDoc(escapeQuote).booleanValue());
230
231     String JavaDoc escapeCharacter = (String JavaDoc) cjdbcUrlParameters
232         .get(Driver.ESCAPE_CHARACTER_PROPERTY);
233     if (escapeCharacter != null)
234       setEscapeChar(escapeCharacter);
235
236     String JavaDoc isDriverProcessed = (String JavaDoc) cjdbcUrlParameters
237         .get(Driver.DRIVER_PROCESSED_PROPERTY);
238     if (isDriverProcessed != null)
239       setDriverProcessed(Boolean.valueOf(isDriverProcessed).booleanValue());
240
241     // true if transparent connection pooling must be used
242
this.connectionPooling = !"false".equals(cjdbcUrlParameters
243         .get(Driver.CONNECTION_POOLING_PROPERTY));
244
245     if (cjdbcUrl.isDebugEnabled())
246     {
247       // Give a warning for unrecognized driver options
248
for (Iterator JavaDoc iter = cjdbcUrlParameters.entrySet().iterator(); iter
249           .hasNext();)
250       {
251         Map.Entry JavaDoc e = (Map.Entry JavaDoc) iter.next();
252         String JavaDoc param = (String JavaDoc) e.getKey();
253         if (!Driver.driverProperties.contains(param))
254           System.out.println("Unrecognized driver parameter: " + param + " = "
255               + (String JavaDoc) e.getValue());
256       }
257     }
258   }
259
260   /**
261    * @see java.lang.Object#finalize()
262    */

263   protected void finalize() throws Throwable JavaDoc
264   {
265     if (this.closeSocketOnGC)
266     {
267       Throwable JavaDoc t = null;
268       try
269       {
270         rollback();
271       }
272       catch (Exception JavaDoc e)
273       {
274         t = e;
275       }
276       try
277       {
278         close();
279       }
280       catch (Exception JavaDoc e)
281       {
282         t = e;
283       }
284
285       if (t != null)
286       {
287         throw t;
288       }
289
290     }
291     super.finalize();
292   }
293
294   /**
295    * Gets the C-JDBC URL of the database of the connection.
296    *
297    * @return value of url.
298    */

299   public String JavaDoc getUrl()
300   {
301     return cjdbcUrl.getUrl();
302   }
303
304   /**
305    * Gets the user name used to login to the database.
306    *
307    * @return login name
308    */

309   public String JavaDoc getUserName()
310   {
311     return vdbUser;
312   }
313
314   /**
315    * Gets the password used to login to the database.
316    *
317    * @return password
318    */

319   public String JavaDoc getPassword()
320   {
321     return vdbPassword;
322   }
323
324   /**
325    * Get the information about the controller we are connected to
326    *
327    * @return <code>ControllerInfo</code> object of the controller
328    */

329   public ControllerInfo getControllerInfo()
330   {
331     return controllerInfo;
332   }
333
334   //
335
// Connection interface methods
336
//
337

338   /**
339    * After this call, <code>getWarnings()</code> returns <code>null</code>
340    * until a new warning is reported for this connection.
341    */

342   public void clearWarnings()
343   {
344     firstWarning = null;
345   }
346
347   /**
348    * @see #close()
349    */

350   private void throwSQLExceptionIfClosed(String JavaDoc message)
351       throws DriverSQLException
352   {
353     if (isClosed)
354       throw new DriverSQLException(message);
355   }
356
357   /**
358    * @see #close()
359    */

360   private void throwSQLExceptionIfClosed() throws DriverSQLException
361   {
362     // default message
363
throwSQLExceptionIfClosed("Tried to operate on a closed Connection");
364   }
365
366   /**
367    * Releases the connection. In fact, the connection is marked to be released
368    * but will be effectively closed by the <code>ConnectionClosingThread</code>
369    * if the connection has not been reused before.
370    *
371    * @exception DriverSQLException if an error occurs
372    */

373   public void close() throws DriverSQLException
374   {
375     synchronized (this) // Wait until other methods/Commands are done
376
{
377       throwSQLExceptionIfClosed();
378       isClosed = true;
379       /*
380        * All JDBC entry points (methods) of this Connection have to
381        * throwSQLExceptionIfClosed(). Relaxed: at least every JDBC method _with
382        * some side-effect_ has to throwSQLExceptionIfClosed(). So now we are
383        * safe and can leave the lock, since they will fail anyway.
384        */

385     }
386
387     if (connectionPooling)
388     { // Try to pool the connection for later reuse
389
try
390       {
391         if (cjdbcUrl.isDebugEnabled())
392           System.out.println("Resetting connection and adding it to the pool");
393         autoCommit = true;
394         readOnly = false;
395         socketOutput.writeInt(Commands.Reset);
396         socketOutput.flush();
397       }
398       catch (IOException JavaDoc e)
399       {
400         throw new DriverSQLException("I/O Error while closing the connection\n"
401             + e.getLocalizedMessage(), e);
402       }
403
404       // only one (Connection) accessing the pool at a time
405
synchronized (driver.pendingConnectionClosing)
406       {
407         if (!driver.connectionClosingThreadisAlive)
408         { // First connection to close, start a new closing thread
409
if (cjdbcUrl.isDebugEnabled())
410             System.out.println("Starting a new connection closing thread");
411           ConnectionClosingThread t = new ConnectionClosingThread(driver);
412           t.start();
413         }
414         // Add to the list
415
driver.pendingConnectionClosing.add(this);
416       }
417     }
418     else
419     { // Close connection
420
try
421       {
422         driver = null; // probably useless since we use now
423
// throwSQLExceptionIfClosed(), but
424
// harmless anyway
425
if (socketOutput != null)
426         {
427           if (cjdbcUrl.isDebugEnabled())
428             System.out.println("Closing connection");
429           socketOutput.writeInt(Commands.Close);
430           socketOutput.flush();
431           if (socketInput != null)
432           { // Wait for the controller to receive the connection and close the
433
// stream. If we do not wait for the controller ack, the connection
434
// is closed on the controller before the closing is handled which
435
// results in an ugly warning message on the controller side. We are
436
// not in a hurry when closing the connection so let do the things
437
// nicely!
438
receiveBoolean();
439             socketInput.close();
440           }
441           socketOutput.close();
442         }
443
444         if (socket != null)
445           socket.close();
446       }
447       catch (Exception JavaDoc ignore)
448       {
449       }
450     }
451   }
452
453   /**
454    * Makes all changes made since the previous commit/rollback permanent and
455    * releases any database locks currently held by the <code>Connection</code>.
456    * This method should only be used when auto-commit has been disabled. (If
457    * <code>autoCommit</code>== <code>true</code>, then we throw a
458    * DriverSQLException).
459    *
460    * @exception DriverSQLException if a database access error occurs or the
461    * connection is in autocommit mode
462    * @see Connection#setAutoCommit(boolean)
463    */

464   public synchronized void commit() throws DriverSQLException
465   {
466     throwSQLExceptionIfClosed();
467     if (autoCommit)
468       throw new DriverSQLException(
469           "Trying to commit a connection in autocommit mode");
470
471     long firstTransactionId = this.transactionId;
472     try
473     {
474       socketOutput.writeInt(Commands.Commit);
475       socketOutput.flush();
476       // Commit is followed by a BEGIN
477
this.transactionId = receiveLong();
478       writeExecutedInTransaction = false;
479       if (cjdbcUrl.isDebugEnabled())
480         System.out.println("New transaction " + transactionId
481             + " has been started");
482     }
483     catch (SerializableException e)
484     {
485       throw new DriverSQLException(e);
486     }
487     catch (IOException JavaDoc e)
488     {
489       throw new DriverSQLException(
490           "I/O Error occured around commit of transaction '"
491               + firstTransactionId + "\n" + e.getLocalizedMessage(), e);
492     }
493   }
494
495   /**
496    * SQL statements without parameters are normally executed using
497    * <code>Statement</code> objects. If the same SQL statement is executed
498    * many times, it is more efficient to use a <code>PreparedStatement</code>.
499    * The <code>ResultSet</code> will be
500    * <code>TYPE_FORWARD_ONLY</cde>/<code>CONCUR_READ_ONLY</code>.
501    * *
502    * @return a new <code>Statement</code> object
503    * @exception DriverSQLException passed through from the constructor
504    */

505   public java.sql.Statement JavaDoc createStatement() throws DriverSQLException
506   {
507     throwSQLExceptionIfClosed();
508     return new Statement(this);
509   }
510
511   /**
512    * SQL statements without parameters are normally executed using
513    * <code>Statement</code> objects. If the same SQL statement is executed
514    * many times, it is more efficient to use a <code>PreparedStatement</code>.
515    *
516    * @param resultSetType resultSetType to use
517    * @param resultSetConcurrency resultSetConcurrency to use
518    * @return a new <code>Statement</code> object
519    * @exception SQLException passed through from the constructor
520    */

521   public java.sql.Statement JavaDoc createStatement(int resultSetType,
522       int resultSetConcurrency) throws SQLException JavaDoc
523   {
524     throwSQLExceptionIfClosed();
525     Statement s = new Statement(this);
526     s.setResultSetType(resultSetType);
527     s.setResultSetConcurrency(resultSetConcurrency);
528     return s;
529   }
530
531   /**
532    * Gets the current auto-commit state.
533    *
534    * @return current state of the auto-commit mode
535    * @exception DriverSQLException is connection is closed
536    * @see Connection#setAutoCommit
537    */

538   public boolean getAutoCommit() throws DriverSQLException
539   {
540     throwSQLExceptionIfClosed();
541     return this.autoCommit;
542   }
543
544   /**
545    * A connection's database is able to provide information describing its
546    * tables, its supported SQL grammar, its stored procedures, the capabilities
547    * of this connection, etc. This information is made available through a
548    * DatabaseMetaData object.
549    *
550    * @return a <code>DatabaseMetaData</code> object for this connection
551    * @exception DriverSQLException if connection is closed
552    */

553   public java.sql.DatabaseMetaData JavaDoc getMetaData() throws DriverSQLException
554   {
555     throwSQLExceptionIfClosed();
556     if (metaData == null)
557     {
558       metaData = new DatabaseMetaData(this);
559     }
560     return metaData;
561   }
562
563   /**
564    * Return current catalog name.
565    *
566    * @return name of the current <code>VirtualDatabase</code>
567    * @throws DriverSQLException if any error occurs
568    * @see Connection#getCatalog()
569    */

570   public synchronized String JavaDoc getCatalog() throws DriverSQLException
571   {
572     throwSQLExceptionIfClosed();
573     try
574     {
575       socketOutput.writeInt(Commands.ConnectionGetCatalog);
576       socketOutput.flush();
577
578       if (cjdbcUrl.isDebugEnabled())
579         System.out.println("Connection.getCatalog");
580
581       return receiveString();
582     }
583     catch (SerializableException e)
584     {
585       throw new DriverSQLException(e);
586     }
587     catch (IOException JavaDoc e)
588     {
589       throw wrapIOExceptionInDriverSQLException("getCatalog", e);
590     }
591   }
592
593   /**
594    * getCatalogs definition.
595    *
596    * @return instace of <code>ResultSet<code>
597    * @throws DriverSQLException if fails (include ANY exception that can be thrown in the code)
598    */

599   public synchronized ResultSet JavaDoc getCatalogs() throws DriverSQLException
600   {
601     throwSQLExceptionIfClosed();
602     String JavaDoc myName = "Connection.getCatalogs";
603     try
604     {
605       socketOutput.writeInt(Commands.ConnectionGetCatalogs);
606       socketOutput.flush();
607
608       if (cjdbcUrl.isDebugEnabled())
609         System.out.println(myName);
610
611       return receiveResultSet(myName);
612     }
613     catch (SerializableException e)
614     {
615       throw new DriverSQLException(e);
616     }
617     catch (IOException JavaDoc e)
618     {
619       throw wrapIOExceptionInDriverSQLException("getCatalogs", e);
620     }
621   }
622
623   protected synchronized java.sql.ResultSet JavaDoc getProcedures(String JavaDoc catalog,
624       String JavaDoc schemaPattern, String JavaDoc procedureNamePattern)
625       throws DriverSQLException
626   {
627     throwSQLExceptionIfClosed();
628     String JavaDoc myName = "Connection.getProcedures";
629     try
630     {
631       socketOutput.writeInt(Commands.DatabaseMetaDataGetProcedures);
632       socketOutput.writeUTF(catalog);
633       socketOutput.writeUTF(schemaPattern);
634       socketOutput.writeUTF(procedureNamePattern);
635       socketOutput.flush();
636
637       if (cjdbcUrl.isDebugEnabled())
638         System.out.println(myName + "(" + catalog + "," + schemaPattern + ","
639             + procedureNamePattern + ")");
640
641       return receiveResultSet(myName);
642     }
643     catch (SerializableException e)
644     {
645       throw new DriverSQLException(e);
646     }
647     catch (IOException JavaDoc e)
648     {
649       throw wrapIOExceptionInDriverSQLException("getProcedures", e);
650     }
651   }
652
653   protected synchronized java.sql.ResultSet JavaDoc getProcedureColumns(String JavaDoc catalog,
654       String JavaDoc schemaPattern, String JavaDoc procedureNamePattern,
655       String JavaDoc columnNamePattern) throws DriverSQLException
656   {
657     throwSQLExceptionIfClosed();
658     String JavaDoc myName = "Connection.getProcedureColumns";
659     try
660     {
661       socketOutput.writeInt(Commands.DatabaseMetaDataGetProcedureColumns);
662       socketOutput.writeUTF(catalog);
663       socketOutput.writeUTF(schemaPattern);
664       socketOutput.writeUTF(procedureNamePattern);
665       socketOutput.writeUTF(columnNamePattern);
666       socketOutput.flush();
667
668       if (cjdbcUrl.isDebugEnabled())
669         System.out.println(myName + "(" + catalog + "," + schemaPattern + ","
670             + procedureNamePattern + "," + columnNamePattern + ")");
671
672       return receiveResultSet(myName);
673     }
674     catch (SerializableException e)
675     {
676       throw new DriverSQLException(e);
677     }
678     catch (IOException JavaDoc e)
679     {
680       throw wrapIOExceptionInDriverSQLException("getProcedureColumns", e);
681     }
682   }
683
684   /**
685    * Gets this Connection's current transaction isolation mode. If the
686    * transaction isolation has not been set using setTransactionIsolation, this
687    * method will return by default
688    * java.sql.Connection.TRANSACTION_READ_UNCOMMITTED whatever transaction
689    * isolation is really used by the cluster nodes. If you want to enfore
690    * TRANSACTION_READ_UNCOMMITTED, you have to explicitely call
691    * setTransactionIsolation(java.sql.Connection.TRANSACTION_READ_UNCOMMITTED)
692    *
693    * @return the current <code>TRANSACTION_*</code> mode value
694    * @exception DriverSQLException if a database access error occurs
695    * @see #setTransactionIsolation(int)
696    */

697   public int getTransactionIsolation() throws DriverSQLException
698   {
699     throwSQLExceptionIfClosed();
700     // Warning, here we assume that if no transaction isolation is set the
701
// database will provide READ_UNCOMMITED.
702
if (isolationLevel == DEFAULT_TRANSACTION_ISOLATION_LEVEL)
703       return java.sql.Connection.TRANSACTION_READ_UNCOMMITTED;
704     return isolationLevel;
705   }
706
707   /**
708    * C-JDBC does NOT support type map.
709    *
710    * @return an exception
711    * @exception SQLException not supported
712    */

713   public java.util.Map JavaDoc getTypeMap() throws SQLException JavaDoc
714   {
715     throw new NotImplementedException("getTypeMap()");
716   }
717
718   /**
719    * The first warning reported by calls on this connection is returned. <B>
720    * Note: </B> Sebsequent warnings will be changed to this SQLWarning
721    *
722    * @return the first SQLWarning or null
723    */

724   public SQLWarning JavaDoc getWarnings()
725   {
726     return firstWarning;
727   }
728
729   /**
730    * Returns <code>true</code> if the connection has been closed by the user
731    * (but C-JDBC may leave it open underneath, unknown to the user).
732    *
733    * @return <code>true</code> if connection has never been opened or
734    * <code>close()</code> has been called
735    */

736   public boolean isClosed()
737   {
738     return isClosed;
739   }
740
741   /**
742    * Tests to see if the connection is in read only Mode. Note that we cannot
743    * really put the database in read only mode, but we pretend we can by
744    * returning the value of the <code>readOnly</code> flag.
745    *
746    * @return <code>true</code> if the connection is read only
747    */

748   public boolean isReadOnly()
749   {
750     return readOnly;
751   }
752
753   /**
754    * As we can't know for sure which database will execute this request (now or
755    * later), we can't translate it in the native query language of the
756    * underlying DBMS. Therefore the query is returned unchanged.
757    *
758    * @param query the query to change
759    * @return the original query
760    */

761   public String JavaDoc nativeSQL(String JavaDoc query)
762   {
763     return query;
764   }
765
766   /**
767    * Creates a CallableStatement that contains sql and produces a ResultSet that
768    * is TYPE_SCROLL_INSENSITIVE and CONCUR_READ_ONLY.
769    *
770    * @param sql SQL request
771    * @return nothing
772    * @exception SQLException not supported
773    */

774   public java.sql.CallableStatement JavaDoc prepareCall(String JavaDoc sql) throws SQLException JavaDoc
775   {
776     throwSQLExceptionIfClosed();
777     return prepareCall(sql, java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE,
778         java.sql.ResultSet.CONCUR_READ_ONLY);
779   }
780
781   /**
782    * Stored procedure call are not yet supported by C-JDBC.
783    *
784    * @param sql a <code>String</code> value
785    * @param resultSetType an <code>int</code> value
786    * @param resultSetConcurrency an <code>int</code> value
787    * @return nothing
788    * @exception SQLException not supported
789    */

790   public java.sql.CallableStatement JavaDoc prepareCall(String JavaDoc sql, int resultSetType,
791       int resultSetConcurrency) throws SQLException JavaDoc
792   {
793     throwSQLExceptionIfClosed();
794     CallableStatement c = new CallableStatement(this, sql);
795     c.setResultSetType(resultSetType);
796     c.setResultSetConcurrency(resultSetConcurrency);
797     return c;
798   }
799
800   /**
801    * A SQL statement with or without <code>IN</code> parameters can be
802    * pre-compiled and stored in a PreparedStatement object. This object can then
803    * be used to efficiently execute this statement multiple times.
804    *
805    * @param sql a SQL statement that may contain one or more '?' IN * parameter
806    * placeholders
807    * @return a new <code>PreparedStatement</code> object containing the
808    * pre-compiled statement.
809    * @exception SQLException if a database access error occurs.
810    */

811   public java.sql.PreparedStatement JavaDoc prepareStatement(String JavaDoc sql)
812       throws SQLException JavaDoc
813   {
814     throwSQLExceptionIfClosed();
815     return new PreparedStatement(this, sql);
816   }
817
818   /**
819    * A SQL statement with or without IN parameters can be pre-compiled and
820    * stored in a <code>PreparedStatement</code> object. This object can then
821    * be used to efficiently execute this statement multiple times.
822    *
823    * @param sql a SQL statement that may contain one or more '?' IN
824    * @param resultSetType <code>ResultSetType</code> to use
825    * @param resultSetConcurrency <code>ResultSetConcurrency</code> to use
826    * @return a new <code>PreparedStatement</code> object
827    * @exception SQLException passed through from the constructor
828    */

829   public java.sql.PreparedStatement JavaDoc prepareStatement(String JavaDoc sql,
830       int resultSetType, int resultSetConcurrency) throws SQLException JavaDoc
831   {
832     throwSQLExceptionIfClosed();
833     PreparedStatement s = new PreparedStatement(this, sql);
834     s.setResultSetType(resultSetType);
835     s.setResultSetConcurrency(resultSetConcurrency);
836     return s;
837   }
838
839   /**
840    * Drops all changes made since the previous commit/rollback and releases any
841    * database locks currently held by this connection. If the connection was in
842    * autocommit mode, we throw a DriverSQLException.
843    *
844    * @exception DriverSQLException if a database access error occurs or the
845    * connection is in autocommit mode
846    * @see Connection#commit()
847    */

848   public synchronized void rollback() throws DriverSQLException
849   {
850     throwSQLExceptionIfClosed();
851     if (autoCommit)
852       throw new DriverSQLException(
853           "Trying to rollback a connection in autocommit mode");
854
855     long initialTransactionId = this.transactionId;
856     try
857     {
858       socketOutput.writeInt(Commands.Rollback);
859       socketOutput.flush();
860       // Rollback is followed by a BEGIN
861
this.transactionId = receiveLong();
862       writeExecutedInTransaction = false;
863
864       if (cjdbcUrl.isDebugEnabled())
865         System.out
866             .println("Transaction " + transactionId + " has been started");
867     }
868     catch (SerializableException e)
869     {
870       throw new DriverSQLException(e);
871     }
872     catch (IOException JavaDoc e)
873     {
874       throw new DriverSQLException(
875           "I/O Error occured around rollback of transaction '"
876               + initialTransactionId + "\n" + e.getLocalizedMessage(), e);
877     }
878   }
879
880   /**
881    * If a connection is in auto-commit mode, then all its SQL statements will be
882    * executed and committed as individual transactions. Otherwise, its SQL
883    * statements are grouped into transactions that are terminated by either
884    * {@link #commit()}or {@link #rollback()}. By default, new connections are
885    * in auto-commit mode. The commit occurs when the statement completes or the
886    * next execute occurs, whichever comes first. In the case of statements
887    * returning a <code>ResultSet</code>, the statement completes when the
888    * last row of the <code>ResultSet</code> has been retrieved or the
889    * <code>ResultSet</code> has been closed. In advanced cases, a single
890    * statement may return multiple results as well as output parameter values.
891    * Here the commit occurs when all results and output param values have been
892    * retrieved.
893    *
894    * @param autoCommit <code>true</code> enables auto-commit;
895    * <code>false</code> disables it
896    * @exception DriverSQLException if a database access error occurs
897    */

898   public synchronized void setAutoCommit(boolean autoCommit)
899       throws DriverSQLException
900   {
901     throwSQLExceptionIfClosed();
902     if (this.autoCommit == autoCommit)
903       return;
904
905     if (autoCommit)
906     { // enable autocommit
907
try
908       {
909         if (cjdbcUrl.isDebugEnabled())
910           System.out.println("Setting connection in autocommit mode");
911         socketOutput.writeInt(Commands.SetAutoCommit);
912         socketOutput.flush();
913
914         receiveBoolean();
915         writeExecutedInTransaction = false;
916         transactionId = 0;
917         this.autoCommit = true;
918         return;
919
920       }
921       catch (SerializableException se)
922       {
923         throw new DriverSQLException(se);
924       }
925       catch (IOException JavaDoc e)
926       {
927         throw new DriverSQLException(
928             "Error while trying to enable autocommit\n"
929                 + e.getLocalizedMessage(), e);
930       }
931     }
932     else
933     { // disable autocommit
934
try
935       {
936         socketOutput.writeInt(Commands.Begin);
937         socketOutput.flush();
938
939         transactionId = receiveLong();
940         this.autoCommit = false;
941
942         if (cjdbcUrl.isDebugEnabled())
943           System.out.println("Transaction " + transactionId
944               + " has been started");
945       }
946       catch (SerializableException e)
947       {
948         throw new DriverSQLException(e);
949       }
950       catch (IOException JavaDoc e)
951       {
952         throw new DriverSQLException(
953             "I/O Error while trying to disable autocommit\n"
954                 + e.getLocalizedMessage(), e);
955       }
956     }
957   }
958
959   /**
960    * Change the current catalog
961    *
962    * @param catalog a <code>String</code> value
963    * @exception SQLException if fails or if catalog name is invalid
964    */

965   public synchronized void setCatalog(String JavaDoc catalog) throws SQLException JavaDoc
966   {
967     throwSQLExceptionIfClosed();
968     if (catalog == null)
969       throw new DriverSQLException("Invalid Catalog");
970     cjdbcUrl.setUrl(driver.changeDatabaseName(cjdbcUrl.getUrl(), catalog));
971
972     try
973     {
974       socketOutput.writeInt(Commands.ConnectionSetCatalog);
975       socketOutput.writeUTF(catalog);
976       socketOutput.flush();
977
978       if (cjdbcUrl.isDebugEnabled())
979         System.out.println("Connection.setCatalog(" + catalog + ")");
980
981       if (!receiveBoolean())
982         throw new DriverSQLException("Invalid Catalog");
983
984     }
985     catch (SerializableException e)
986     {
987       throw new DriverSQLException(e);
988     }
989     catch (IOException JavaDoc e)
990     {
991       throw wrapIOExceptionInDriverSQLException("setCatalog", e);
992     }
993   }
994
995   /**
996    * You can put a connection in read-only mode as a hint to enable database
997    * optimizations
998    * <p>
999    * <B>Note: </B> setReadOnly cannot be called while in the middle of a
1000   * transaction with write requests.
1001   *
1002   * @param readOnly <code>true</code> enables read-only mode;
1003   * <code>false</code> disables it
1004   * @exception DriverSQLException if a database access error occurs
1005   */

1006  public void setReadOnly(boolean readOnly) throws DriverSQLException
1007  {
1008    throwSQLExceptionIfClosed();
1009    if ((autoCommit == false) && writeExecutedInTransaction)
1010      throw new DriverSQLException(
1011          "setReadOnly cannot be called in a transaction that has executed write requests.");
1012
1013    this.readOnly = readOnly;
1014  }
1015
1016  /**
1017   * You can call this method to try to change the transaction isolation level
1018   * using one of the TRANSACTION_* values.
1019   * <p>
1020   * <B>Note: </B> this method cannot be called while in the middle of a
1021   * transaction.
1022   *
1023   * @param level one of the TRANSACTION_* isolation values with * the exception
1024   * of TRANSACTION_NONE; some databases may * not support other values
1025   * @exception DriverSQLException if a database access error occurs
1026   * @see java.sql.DatabaseMetaData#supportsTransactionIsolationLevel
1027   */

1028  public synchronized void setTransactionIsolation(int level)
1029      throws DriverSQLException
1030  {
1031    throwSQLExceptionIfClosed();
1032    // Check if we are in a transaction or not. We have no trace on the driver
1033
// side if a read query has already been executed or not in the current
1034
// transaction (if any). We let the controller check for this (we only check
1035
// for writes here) as well as if the underlying databases support the
1036
// transaction isolation level. If this is not supported, the driver will
1037
// send back an exception.
1038
if ((autoCommit == false) && writeExecutedInTransaction)
1039      throw new DriverSQLException(
1040          "setTransactionIsolation cannot be called in a transaction that has executed write requests.");
1041
1042    if (level != isolationLevel)
1043    { // Only try to change if there is a new value
1044
if ((level == TRANSACTION_READ_COMMITTED)
1045          || (level == TRANSACTION_READ_UNCOMMITTED)
1046          || (level == TRANSACTION_REPEATABLE_READ)
1047          || (level == TRANSACTION_SERIALIZABLE))
1048      {
1049        try
1050        {
1051          socketOutput.writeInt(Commands.SetTransactionIsolation);
1052          socketOutput.writeInt(level);
1053          socketOutput.flush();
1054
1055          if (cjdbcUrl.isDebugEnabled())
1056            System.out.println("Setting transaction isolation level to "
1057                + level);
1058
1059          receiveBoolean();
1060          // Success
1061
isolationLevel = level;
1062          return;
1063
1064        }
1065        catch (SerializableException e)
1066        {
1067          throw new DriverSQLException(e);
1068        }
1069        catch (IOException JavaDoc ioe)
1070        {
1071          throw new DriverSQLException(
1072              "I/O Error while setting transaction isolation level to " + level
1073                  + "\n" + ioe.getLocalizedMessage(), ioe);
1074        }
1075      }
1076      else
1077        throw new DriverSQLException("Invalid transaction isolation level "
1078            + level);
1079    } // we were already in that level; do nothing.
1080
}
1081
1082  /**
1083   * C-JDBC does NOT support type map.
1084   *
1085   * @param map ignored
1086   * @exception SQLException not supported
1087   */

1088  public void setTypeMap(java.util.Map JavaDoc map) throws SQLException JavaDoc
1089  {
1090    throw new NotImplementedException("setTypeMap()");
1091  }
1092
1093  /*
1094   * Connection C-JDBC internals
1095   */

1096
1097  /**
1098   * Sets the closeSocketOnGC value.
1099   *
1100   * @param closeSocketOnGC The closeSocketOnGC to set.
1101   */

1102  private void setCloseSocketOnGC(boolean closeSocketOnGC)
1103  {
1104    this.closeSocketOnGC = closeSocketOnGC;
1105  }
1106
1107  /**
1108   * Set the autocommit mode and read-only status on this request.
1109   *
1110   * @param request The request to set
1111   */

1112  private void setConnectionParametersOnRequest(AbstractRequest request)
1113  {
1114    request.setIsAutoCommit(autoCommit);
1115    request.setIsReadOnly(readOnly);
1116    request.setDriverProcessed(driverProcessed);
1117  }
1118
1119  /**
1120   * Returns a DriverResultSet read from the stream or throws the
1121   * SerializableException that came instead
1122   *
1123   * @param callerName used for error messages. Is this really useful?
1124   * @return received ResultSet
1125   * @throws IOException stream or protocol error
1126   * @throws SerializableException received from the controller
1127   */

1128  private DriverResultSet receiveResultSet(String JavaDoc callerName)
1129      throws IOException JavaDoc, ProtocolException, SerializableException
1130  {
1131    TypeTag tag = new TypeTag(socketInput);
1132
1133    if (TypeTag.NULL_RESULTSET.equals(tag))
1134      return null;
1135
1136    if (TypeTag.RESULTSET.equals(tag))
1137    {
1138      DriverResultSet drs = new DriverResultSet(this);
1139      return drs;
1140    }
1141
1142    if (TypeTag.EXCEPTION.equals(tag))
1143      throw receiveException();
1144
1145    throw new ProtocolException(callerName
1146        + ": expected a resultset, received unexpected tag: " + tag);
1147  }
1148
1149  /**
1150   * Serialize a procedure on the output stream by sending only the needed
1151   * parameters to reconstruct it on the controller
1152   *
1153   * @param proc the procedure to send
1154   * @param isRead true if this is a read stored procedure
1155   * @throws IOException if fails
1156   */

1157  private void procedureOnStream(StoredProcedure proc, boolean isRead)
1158      throws IOException JavaDoc
1159  {
1160    if (!isRead)
1161      writeExecutedInTransaction = true;
1162
1163    proc.sendToStream(socketOutput, this.controllerNeedsSqlSkeleton);
1164  }
1165
1166  /**
1167   * Serialize a write request on the output stream by sending only the needed
1168   * parameters to reconstruct it on the controller
1169   *
1170   * @param request the write request to send
1171   * @throws IOException if fails
1172   */

1173  private void writeRequestOnStream(AbstractWriteRequest request)
1174      throws IOException JavaDoc
1175  {
1176    if (!autoCommit)
1177      writeExecutedInTransaction = true;
1178    socketOutput.writeInt(org.objectweb.cjdbc.common.sql.RequestType
1179        .getRequestType(request));
1180
1181    request.sendToStream(socketOutput, this.controllerNeedsSqlSkeleton);
1182
1183  }
1184
1185  /**
1186   * Deserialize an exception from the stream: converts explicit protocol typing
1187   * into java types.
1188   *
1189   * @return the deserialized exception read from the stream
1190   * @throws IOException stream error
1191   */

1192  private SerializableException receiveException() throws IOException JavaDoc
1193  {
1194    TypeTag exceptionType = new TypeTag(socketInput);
1195
1196    if (TypeTag.BACKEND_EXCEPTION.equals(exceptionType))
1197      return new BackendDriverException(socketInput);
1198    if (TypeTag.CORE_EXCEPTION.equals(exceptionType))
1199      return new ControllerCoreException(socketInput);
1200
1201    throw new ProtocolException("received unknown exception type");
1202  }
1203
1204  /**
1205   * Returns a String read from the stream or throws the SerializableException
1206   * that came instead.
1207   *
1208   * @throws IOException stream or protocol error
1209   * @throws SerializableException coming from the controller
1210   */

1211  private String JavaDoc receiveString() throws IOException JavaDoc, SerializableException
1212  {
1213    TypeTag tag = new TypeTag(socketInput);
1214    if (TypeTag.NOT_EXCEPTION.equals(tag))
1215    {
1216      String JavaDoc answer = socketInput.readUTF();
1217      return answer;
1218    }
1219
1220    throw receiveException();
1221  }
1222
1223  /**
1224   * Returns a boolean read from the stream or throws the SerializableException
1225   * that came instead.
1226   *
1227   * @throws IOException stream or protocol error
1228   * @throws SerializableException coming from the controller
1229   */

1230  private boolean receiveBoolean() throws IOException JavaDoc, SerializableException
1231  {
1232    TypeTag tag = new TypeTag(socketInput);
1233    if (TypeTag.NOT_EXCEPTION.equals(tag))
1234    {
1235      boolean answer = socketInput.readBoolean();
1236      return answer;
1237    }
1238
1239    throw receiveException();
1240  }
1241
1242  /**
1243   * Returns a int read from the stream or throws the SerializableException that
1244   * came instead.
1245   *
1246   * @throws IOException stream or protocol error
1247   * @throws SerializableException coming from the controller
1248   */

1249  private int receiveInt() throws IOException JavaDoc, SerializableException
1250  {
1251    TypeTag tag = new TypeTag(socketInput);
1252    if (TypeTag.NOT_EXCEPTION.equals(tag))
1253    {
1254      int answer = socketInput.readInt();
1255      return answer;
1256    }
1257
1258    throw receiveException();
1259  }
1260
1261  /**
1262   * Returns a long read from the stream or throws the SerializableException
1263   * that came instead.
1264   *
1265   * @throws IOException stream or protocol error
1266   * @throws SerializableException coming from the controller
1267   */

1268  private long receiveLong() throws IOException JavaDoc, SerializableException
1269  {
1270    TypeTag tag = new TypeTag(socketInput);
1271    if (TypeTag.NOT_EXCEPTION.equals(tag))
1272    {
1273      long answer = socketInput.readLong();
1274      return answer;
1275    }
1276
1277    throw receiveException();
1278  }
1279
1280  /**
1281   * Serialize a savepoint on the output stream by sending only the needed
1282   * parameters to reconstruct it on the controller
1283   *
1284   * @param savepoint the savepoint to send
1285   * @throws IOException if fails
1286   */

1287  private void savepointOnStream(Savepoint savepoint) throws IOException JavaDoc
1288  {
1289    writeExecutedInTransaction = true;
1290
1291    try
1292    {
1293      socketOutput.writeUTF(savepoint.getSavepointName());
1294      return;
1295    }
1296    catch (SQLException JavaDoc ignore)
1297    {
1298      // Ignoring because we are dealing with an un-named savepoint
1299
}
1300
1301    try
1302    {
1303      socketOutput.writeUTF(String.valueOf(savepoint.getSavepointId()));
1304      return;
1305    }
1306    catch (SQLException JavaDoc ignore)
1307    {
1308      // We should never get here
1309
}
1310  }
1311
1312  /**
1313   * Try first to reconnect to the same controller and if we don't succeed then
1314   * we notify the suspicion of failure if the current controller and we
1315   * reconnect to a controller chosen using the policy specified in the JDBC URL
1316   * of this connection. FIXME: we need a less coarse exception signature
1317   *
1318   * @throws DriverSQLException if an error occured during reconnect
1319   */

1320  private synchronized void reconnect() throws DriverSQLException
1321  {
1322    // Get rid of current connection
1323
try
1324    {
1325      this.socket.close();
1326    }
1327    catch (IOException JavaDoc ignore)
1328    {
1329    }
1330    try
1331    {
1332      this.socketInput.close();
1333    }
1334    catch (IOException JavaDoc ignore)
1335    {
1336    }
1337    try
1338    {
1339      this.socketOutput.close();
1340    }
1341    catch (IOException JavaDoc ignore)
1342    {
1343    }
1344    // only one (Connection) accessing the pool at a time
1345
synchronized (driver.pendingConnectionClosing)
1346    {
1347      if (driver.pendingConnectionClosing.remove(this))
1348        System.out.println("Warning! Closed call before reconnect");
1349    }
1350
1351    Connection newconn = null;
1352    // The CjdbcUrl does not carry the login/password info so we have to
1353
// re-create these properties to reconnect
1354
Properties JavaDoc properties = new Properties JavaDoc();
1355    properties.setProperty(Driver.USER_PROPERTY, vdbUser);
1356    properties.setProperty(Driver.PASSWORD_PROPERTY, vdbPassword);
1357
1358    AbstractControllerConnectPolicy controllerConnectPolicy = cjdbcUrl
1359        .getControllerConnectPolicy();
1360    // If we are the first to fail on this controller, we have to retry it might
1361
// just be our connection that has been lost.
1362
if (!controllerConnectPolicy.isSuspectedOfFailure(controllerInfo))
1363    { // Let's retry the current controller
1364
try
1365      {
1366        newconn = (Connection) driver.connectToController(properties, cjdbcUrl,
1367            controllerInfo);
1368        if (cjdbcUrl.isDebugEnabled())
1369          System.out.println("Succeeded to reconnect to current controller: "
1370              + controllerInfo);
1371      }
1372      catch (Exception JavaDoc e)
1373      {
1374        if (cjdbcUrl.isDebugEnabled())
1375          System.out.println("Failed to reconnect to current controller "
1376              + controllerInfo);
1377        newconn = null; // flag that we failed
1378
controllerConnectPolicy.suspectControllerOfFailure(controllerInfo);
1379      }
1380    }
1381
1382    if (newconn == null)
1383    {
1384      try
1385      {
1386        // At this point, the current controller is down and we have to try a
1387
// new one that will be allocated by the policy specified in the URL.
1388
controllerInfo = controllerConnectPolicy.getController();
1389        if (cjdbcUrl.isDebugEnabled())
1390          System.out.println("Trying to reconnect to another controller: "
1391              + controllerInfo);
1392        newconn = (Connection) driver.connectToController(properties, cjdbcUrl,
1393            controllerInfo);
1394      }
1395      catch (AuthenticationException e)
1396      {
1397        // Should not happen, this probably mean an inconsistency in controller
1398
// configuration but safely ignore (see below)
1399
String JavaDoc msg = "Warning! Authentication exception received on connection retry, controller configuration might be inconsistent";
1400        if (cjdbcUrl.isInfoEnabled())
1401          System.out.println(msg);
1402        throw new DriverSQLException(msg, e);
1403      }
1404      catch (NoMoreControllerException nmc)
1405      {
1406        throw new DriverSQLException(nmc);
1407      }
1408      catch (DriverSQLException e1)
1409      {
1410        // Impossible to connect to the new controller
1411
String JavaDoc msg = "Failed to reconnect to other controller: "
1412            + controllerInfo;
1413        if (cjdbcUrl.isDebugEnabled())
1414          System.out.println(msg);
1415        newconn = null;
1416        controllerConnectPolicy.suspectControllerOfFailure(controllerInfo);
1417        throw new DriverSQLException(msg, e1);
1418      }
1419    }
1420
1421    // success: let's steal the new connection for ourselves
1422
newconn.setCloseSocketOnGC(false);
1423    this.socket = newconn.socket;
1424    this.socketInput = newconn.socketInput;
1425    this.socketOutput = newconn.socketOutput;
1426    this.controllerInfo = newconn.controllerInfo;
1427    this.isClosed = false;
1428    try
1429    {
1430      if (cjdbcUrl.isDebugEnabled())
1431        System.out.println("Restoring connection state on controller "
1432            + controllerInfo);
1433      socketOutput.writeInt(Commands.RestoreConnectionState);
1434      socketOutput.writeBoolean(autoCommit);
1435      if (!autoCommit)
1436        socketOutput.writeLong(transactionId);
1437    }
1438    catch (IOException JavaDoc e)
1439    {
1440      throw new DriverSQLException("Failed to reconnect to controller\n"
1441          + e.getLocalizedMessage(), e);
1442    }
1443  }
1444
1445  /**
1446   * Performs a read request and return the reply.
1447   *
1448   * @param request the read request to execute
1449   * @return a <code>java.sql.ResultSet</code> value
1450   * @exception DriverSQLException if an error occurs
1451   */

1452  protected synchronized java.sql.ResultSet JavaDoc execReadRequest(
1453      SelectRequest request) throws DriverSQLException
1454  {
1455    throwSQLExceptionIfClosed("Closed connection cannot process request '"
1456        + request.getSQLShortForm(Constants.SQL_SHORT_FORM_LENGTH) + "'");
1457
1458    try
1459    {
1460      setConnectionParametersOnRequest(request);
1461      socketOutput.writeInt(Commands.ExecReadRequest);
1462      request.sendToStream(socketOutput, this.controllerNeedsSqlSkeleton);
1463      socketOutput.flush();
1464      if (cjdbcUrl.isDebugEnabled())
1465        System.out.println("Executing read request " + request);
1466
1467      TypeTag tag = new TypeTag(socketInput);
1468
1469      // First case, we received our ResultSet, let's fetch it.
1470
if (TypeTag.RESULTSET.equals(tag))
1471      {
1472        try
1473        {
1474          java.sql.ResultSet JavaDoc drs = new DriverResultSet(this);
1475          return drs;
1476        }
1477        catch (ProtocolException e)
1478        {
1479          throw new DriverSQLException(
1480              "Protocol corruption in Connection.execReadRequest"
1481                  + " with request "
1482                  + request.getSQLShortForm(Constants.SQL_SHORT_FORM_LENGTH), e);
1483        }
1484        catch (IOException JavaDoc e)
1485        { // Error while reading, retry
1486
if (cjdbcUrl.isInfoEnabled())
1487            System.out.println("IOException occured trying to reconnect ("
1488                + e.getLocalizedMessage() + ")");
1489          reconnect();
1490          return execReadRequest(request);
1491        }
1492      }
1493
1494      if (TypeTag.NULL_RESULTSET.equals(tag))
1495        return null;
1496
1497      // From this point on, we had an exception
1498
if (TypeTag.EXCEPTION.equals(tag))
1499      {
1500        Exception JavaDoc recvEx = null;
1501        recvEx = receiveException();
1502        // dirty hack until cleanup
1503
if (recvEx instanceof ControllerCoreException)
1504          recvEx = ((ControllerCoreException) recvEx)
1505              .compatibilityWrapperHack();
1506
1507        if (recvEx instanceof NoMoreBackendException)
1508        {
1509          if (cjdbcUrl.isInfoEnabled())
1510            System.out.println("No more backend available on controller");
1511          try
1512          {
1513            // If there is only one controller available rethrow the exception
1514
if (cjdbcUrl.getControllerList().length == 1)
1515              throw new DriverSQLException(recvEx);
1516            else
1517            {
1518              // otherwise try to connect to an other controller and re-execute
1519
// the query
1520
reconnect();
1521              // a recursive call in a catch clause is probably not a very good
1522
// idea why not a simple retry loop ?
1523
return execReadRequest(request);
1524            }
1525          }
1526          catch (SQLException JavaDoc e1)
1527          {
1528            // We deal with this exception in the follwoing if block
1529
recvEx = e1;
1530          }
1531        }
1532        else if (recvEx instanceof IOException JavaDoc)
1533        {
1534          if (cjdbcUrl.isInfoEnabled())
1535            System.out.println("IOException occured trying to reconnect ("
1536                + ((IOException JavaDoc) recvEx).getMessage() + ")");
1537          reconnect();
1538          // a recursive call in a catch clause is probably not a very good idea
1539
// why not a simple retry loop?
1540
return execReadRequest(request);
1541        }
1542        else if (recvEx instanceof BackendDriverException)
1543        {
1544          // TODO: temporary fix until DriverSQLException is fixed
1545
throw new DriverSQLException((SerializableException) recvEx);
1546        }
1547      }
1548
1549      // Error, unexpected answer
1550
throw new ProtocolException(
1551          "Protocol corruption in Connection.execReadRequest for request "
1552              + request.getSQLShortForm(Constants.SQL_SHORT_FORM_LENGTH));
1553    }
1554    catch (RuntimeException JavaDoc e)
1555    {
1556      e.printStackTrace();
1557      throw new DriverSQLException(
1558          "Connection.execReadRequest: Error occured while request '"
1559              + request.getSQLShortForm(Constants.SQL_SHORT_FORM_LENGTH)
1560              + "' was processed by C-JDBC Controller", e);
1561    }
1562    catch (IOException JavaDoc e)
1563    { // Connection failed, try to reconnect and re-exec the query
1564
try
1565      {
1566        if (cjdbcUrl.isInfoEnabled())
1567          System.out.println("IOException occured trying to reconnect ("
1568              + e.getMessage() + ")");
1569        reconnect();
1570        return execReadRequest(request);
1571      }
1572      catch (DriverSQLException e1)
1573      {
1574        throw new DriverSQLException(
1575            "Connection lost while executing request '"
1576                + request.getSQLShortForm(Constants.SQL_SHORT_FORM_LENGTH)
1577                + "' and automatic reconnect failed", e1);
1578      }
1579    }
1580  }
1581
1582  /**
1583   * Performs a write request and return the number of rows affected.
1584   *
1585   * @param request the write request to execute
1586   * @return number of rows affected
1587   * @exception DriverSQLException if an error occurs
1588   */

1589  protected synchronized int execWriteRequest(AbstractWriteRequest request)
1590      throws DriverSQLException
1591  {
1592    throwSQLExceptionIfClosed("Closed connection cannot process request '"
1593        + request.getSQLShortForm(Constants.SQL_SHORT_FORM_LENGTH) + "'");
1594
1595    try
1596    {
1597      setConnectionParametersOnRequest(request);
1598      socketOutput.writeInt(Commands.ExecWriteRequest);
1599      writeRequestOnStream(request);
1600      socketOutput.flush();
1601      if (cjdbcUrl.isDebugEnabled())
1602        System.out.println("Executing write request " + request);
1603
1604      return receiveInt();
1605
1606    }
1607    catch (SerializableException se)
1608    {
1609      throw new DriverSQLException(se);
1610    }
1611    catch (IOException JavaDoc e)
1612    { // Connection failed, try to reconnect and re-exec the query
1613
try
1614      {
1615        reconnect();
1616        // FIXME:
1617
// a recursive call in a catch clause is probably not a very good idea
1618
// why not a simple retry loop ?
1619
return execWriteRequest(request);
1620      }
1621      catch (DriverSQLException e1)
1622      {
1623        throw new DriverSQLException("Connection lost while executing request'"
1624            + request.getSQLShortForm(Constants.SQL_SHORT_FORM_LENGTH)
1625            + "' and automatic reconnect failed (", e1);
1626      }
1627    }
1628  }
1629
1630  /**
1631   * Performs a write request and returns the auto-generated keys
1632   *
1633   * @param request the write request to execute
1634   * @return auto generated keys
1635   * @exception DriverSQLException if an error occurs
1636   */

1637  protected synchronized ResultSet JavaDoc execWriteRequestWithKeys(
1638      AbstractWriteRequest request) throws DriverSQLException
1639  {
1640    throwSQLExceptionIfClosed("Closed Connection cannot process request '"
1641        + request.getSQLShortForm(Constants.SQL_SHORT_FORM_LENGTH) + "'");
1642
1643    try
1644    {
1645      setConnectionParametersOnRequest(request);
1646      socketOutput.writeInt(Commands.ExecWriteRequestWithKeys);
1647      writeRequestOnStream(request);
1648      socketOutput.flush();
1649      if (cjdbcUrl.isDebugEnabled())
1650        System.out.println("Executing write request with keys: " + request);
1651
1652      Exception JavaDoc recvEx = null;
1653      TypeTag tag = new TypeTag(socketInput);
1654
1655      /*
1656       * TODO: the code below is a complete mess. One reason is it's still half
1657       * legacy design from old protocol, half from the new procotol. It could
1658       * easily be made much simpler. We should use #receiveResultSet() TODO:
1659       * test NoMoreBackendException
1660       */

1661      if (TypeTag.NULL_RESULTSET.equals(tag))
1662        return null;
1663
1664      if (TypeTag.EXCEPTION.equals(tag))
1665        recvEx = receiveException();
1666      // dirty hack until cleanup
1667
if (recvEx instanceof ControllerCoreException)
1668        recvEx = ((ControllerCoreException) recvEx).compatibilityWrapperHack();
1669
1670      if (recvEx instanceof BackendDriverException)
1671        throw new DriverSQLException(recvEx);
1672      else if (!TypeTag.RESULTSET.equals(tag))
1673      {
1674        throw new DriverSQLException(
1675            "Connection.execWriteRequestWithKeys: Unexpected response "
1676                + "for request "
1677                + request.getSQLShortForm(Constants.SQL_SHORT_FORM_LENGTH),
1678            recvEx);
1679      }
1680      else
1681      {
1682        DriverResultSet drs;
1683        try
1684        {
1685          drs = new DriverResultSet(this);
1686        }
1687        catch (IOException JavaDoc e)
1688        {
1689          throw new DriverSQLException(
1690              "Connection.execWriteRequestWithKeys: IOException "
1691                  + e.getLocalizedMessage()
1692                  + " while reading keys RS for request "
1693                  + request.getSQLShortForm(Constants.SQL_SHORT_FORM_LENGTH), e);
1694        }
1695        return drs;
1696      }
1697
1698    }
1699    catch (IOException JavaDoc e)
1700    { // Connection failed, try to reconnect and re-exec the query
1701
try
1702      {
1703        reconnect();
1704        // a recursive call in a catch clause is probably not a very good idea
1705
// why not a simple retry loop?
1706
return execWriteRequestWithKeys(request);
1707      }
1708      catch (DriverSQLException e1)
1709      {
1710        throw new DriverSQLException("Connection lost while executing request'"
1711            + request.getSQLShortForm(Constants.SQL_SHORT_FORM_LENGTH)
1712            + "' and automatic reconnect failed", e1);
1713      }
1714    }
1715  }
1716
1717  /**
1718   * Call a stored procedure that returns a ResultSet.
1719   *
1720   * @param proc the stored procedure call
1721   * @return a <code>java.sql.ResultSet</code> value
1722   * @exception DriverSQLException if an error occurs
1723   */

1724  public synchronized ResultSet JavaDoc execReadStoredProcedure(StoredProcedure proc)
1725      throws DriverSQLException
1726  {
1727    throwSQLExceptionIfClosed("Closed Connection cannot process request '"
1728        + proc.getSQLShortForm(Constants.SQL_SHORT_FORM_LENGTH) + "'");
1729
1730    try
1731    {
1732      setConnectionParametersOnRequest(proc);
1733      socketOutput.writeInt(Commands.ExecReadStoredProcedure);
1734      procedureOnStream(proc, true);
1735      socketOutput.flush();
1736      if (cjdbcUrl.isDebugEnabled())
1737        System.out.println("Executing read stored procedure " + proc);
1738
1739      Exception JavaDoc recvEx = null;
1740      TypeTag tag = new TypeTag(socketInput);
1741
1742      /*
1743       * TODO: the code below is a complete mess. One reason is it's still half
1744       * legacy design from old protocol, half from the new procotol. It could
1745       * easily be made much simpler. We should use #receiveResultSet() TODO:
1746       * test NoMoreBackendException
1747       */

1748      if (TypeTag.NULL_RESULTSET.equals(tag))
1749        return null;
1750
1751      if (TypeTag.EXCEPTION.equals(tag))
1752        recvEx = receiveException();
1753      // dirty hack until cleanup
1754
if (recvEx instanceof ControllerCoreException)
1755        recvEx = ((ControllerCoreException) recvEx).compatibilityWrapperHack();
1756
1757      if (recvEx instanceof BackendDriverException)
1758        throw new DriverSQLException(recvEx);
1759      else if (!TypeTag.RESULTSET.equals(tag))
1760        throw new DriverSQLException(
1761            "Connection.execReadStoredProcedure: Unexpected response "
1762                + " for request "
1763                + proc.getSQLShortForm(Constants.SQL_SHORT_FORM_LENGTH), recvEx);
1764      else
1765      {
1766        DriverResultSet drs;
1767        try
1768        {
1769          drs = new DriverResultSet(this);
1770        }
1771        catch (IOException JavaDoc e)
1772        {
1773          throw new DriverSQLException(
1774              "Connection.execReadStoredProcedure: IOException "
1775                  + "while receiving RS for request "
1776                  + proc.getSQLShortForm(Constants.SQL_SHORT_FORM_LENGTH), e);
1777        }
1778        return drs;
1779      }
1780    }
1781    catch (RuntimeException JavaDoc e)
1782    {
1783      throw new DriverSQLException(
1784          "Connection.execReadStoredProcedure: Error occured while request '"
1785              + proc.getSQLShortForm(Constants.SQL_SHORT_FORM_LENGTH)
1786              + "' was processed by C-JDBC Controller", e);
1787    }
1788    catch (IOException JavaDoc e)
1789    { // Connection failed, try to reconnect and re-exec the query
1790
try
1791      {
1792        reconnect();
1793        // a recursive call in a catch clause is probably not a very good idea
1794
// why not a simple retry loop ?
1795
return execReadStoredProcedure(proc);
1796      }
1797      catch (DriverSQLException e1)
1798      {
1799        throw new DriverSQLException("Connection lost while executing request'"
1800            + proc.getSQLShortForm(Constants.SQL_SHORT_FORM_LENGTH)
1801            + "' and automatic reconnect failed ", e1);
1802      }
1803    }
1804  }
1805
1806  /**
1807   * Call a stored procedure that performs an update.
1808   *
1809   * @param proc the stored procedure call
1810   * @return number of rows affected
1811   * @exception DriverSQLException if an error occurs
1812   */

1813  protected synchronized int execWriteStoredProcedure(StoredProcedure proc)
1814      throws DriverSQLException
1815  {
1816    throwSQLExceptionIfClosed("Closed Connection cannot process request '"
1817        + proc.getSQLShortForm(Constants.SQL_SHORT_FORM_LENGTH) + "'");
1818
1819    try
1820    {
1821      setConnectionParametersOnRequest(proc);
1822      socketOutput.writeInt(Commands.ExecWriteStoredProcedure);
1823      procedureOnStream(proc, false);
1824      socketOutput.flush();
1825      if (cjdbcUrl.isDebugEnabled())
1826        System.out.println("Executing write stored procedure " + proc);
1827
1828      return receiveInt();
1829
1830    }
1831    catch (SerializableException se)
1832    {
1833      throw new DriverSQLException(se);
1834    }
1835    catch (IOException JavaDoc e)
1836    {
1837      throw new DriverSQLException(
1838          "execWriteStoredProcedure: I/O Error occured while request '"
1839              + proc.getSQLShortForm(Constants.SQL_SHORT_FORM_LENGTH)
1840              + "' was processed by C-JDBC Controller (", e);
1841    }
1842  }
1843
1844  /**
1845   * @see Connection#getBlobFilter()
1846   */

1847  AbstractBlobFilter getBlobFilter()
1848  {
1849    return blobFilter;
1850  }
1851
1852  //
1853
// Database Metadata methods
1854
//
1855

1856  /**
1857   * @see java.sql.DatabaseMetaData#getAttributes(java.lang.String,
1858   * java.lang.String, java.lang.String, java.lang.String)
1859   */

1860  protected synchronized ResultSet JavaDoc getAttributes(String JavaDoc catalog,
1861      String JavaDoc schemaPattern, String JavaDoc typeNamePattern, String JavaDoc attributeNamePattern)
1862      throws DriverSQLException
1863  {
1864    throwSQLExceptionIfClosed();
1865    String JavaDoc myName = "Connection.getAttributes";
1866    try
1867    {
1868      socketOutput.writeInt(Commands.DatabaseMetaDataGetAttributes);
1869      socketOutput.writeUTF(catalog);
1870      socketOutput.writeUTF(schemaPattern);
1871      socketOutput.writeUTF(typeNamePattern);
1872      socketOutput.writeUTF(attributeNamePattern);
1873      socketOutput.flush();
1874
1875      if (cjdbcUrl.isDebugEnabled())
1876        System.out.println(myName + "(" + catalog + "," + schemaPattern + ","
1877            + typeNamePattern + "," + attributeNamePattern + ")");
1878
1879      return receiveResultSet(myName);
1880    }
1881    catch (SerializableException e)
1882    {
1883      throw new DriverSQLException(e);
1884    }
1885    catch (IOException JavaDoc e)
1886    {
1887      throw wrapIOExceptionInDriverSQLException("getAttributes", e);
1888    }
1889  }
1890
1891  /**
1892   * @see java.sql.DatabaseMetaData#getBestRowIdentifier(java.lang.String,
1893   * java.lang.String, java.lang.String, int, boolean)
1894   */

1895  protected synchronized ResultSet JavaDoc getBestRowIdentifier(String JavaDoc catalog,
1896      String JavaDoc schema, String JavaDoc table, int scope, boolean nullable)
1897      throws DriverSQLException
1898  {
1899    throwSQLExceptionIfClosed();
1900    String JavaDoc myName = "Connection.getBestRowIdentifier";
1901    try
1902    {
1903      socketOutput.writeInt(Commands.DatabaseMetaDataGetBestRowIdentifier);
1904      socketOutput.writeUTF(catalog);
1905      socketOutput.writeUTF(schema);
1906      socketOutput.writeUTF(table);
1907      socketOutput.writeInt(scope);
1908      socketOutput.writeBoolean(nullable);
1909      socketOutput.flush();
1910
1911      if (cjdbcUrl.isDebugEnabled())
1912        System.out.println(myName + "(" + catalog + "," + schema + "," + table
1913            + "," + scope + "," + nullable + ")");
1914
1915      return receiveResultSet(myName);
1916    }
1917    catch (SerializableException e)
1918    {
1919      throw new DriverSQLException(e);
1920    }
1921    catch (IOException JavaDoc e)
1922    {
1923      throw wrapIOExceptionInDriverSQLException("getBestRowIdentifier", e);
1924    }
1925  }
1926
1927  /**
1928   * @see java.sql.DatabaseMetaData#getColumnPrivileges(java.lang.String,
1929   * java.lang.String, java.lang.String, java.lang.String)
1930   */

1931  protected synchronized ResultSet JavaDoc getColumnPrivileges(String JavaDoc catalog,
1932      String JavaDoc schemaPattern, String JavaDoc tableName, String JavaDoc columnNamePattern)
1933      throws DriverSQLException
1934  {
1935    throwSQLExceptionIfClosed();
1936    String JavaDoc myName = "Connection.getColumnPrivileges";
1937    try
1938    {
1939      socketOutput.writeInt(Commands.DatabaseMetaDataGetColumnPrivileges);
1940      socketOutput.writeUTF(catalog);
1941      socketOutput.writeUTF(schemaPattern);
1942      socketOutput.writeUTF(tableName);
1943      socketOutput.writeUTF(columnNamePattern);
1944      socketOutput.flush();
1945
1946      if (cjdbcUrl.isDebugEnabled())
1947        System.out.println(myName + "(" + catalog + "," + schemaPattern + ","
1948            + tableName + "," + columnNamePattern + ")");
1949
1950      return receiveResultSet(myName);
1951    }
1952    catch (SerializableException e)
1953    {
1954      throw new DriverSQLException(e);
1955    }
1956    catch (IOException JavaDoc e)
1957    {
1958      throw wrapIOExceptionInDriverSQLException("getColumnPrivileges", e);
1959    }
1960  }
1961
1962  /**
1963   * @see java.sql.DatabaseMetaData#getColumns(java.lang.String,
1964   * java.lang.String, java.lang.String, java.lang.String)
1965   */

1966  protected synchronized ResultSet JavaDoc getColumns(String JavaDoc catalog,
1967      String JavaDoc schemaPattern, String JavaDoc tableNamePattern, String JavaDoc columnNamePattern)
1968      throws DriverSQLException
1969  {
1970    throwSQLExceptionIfClosed();
1971    String JavaDoc myName = "Connection.getColumns";
1972    try
1973    {
1974      socketOutput.writeInt(Commands.DatabaseMetaDataGetColumns);
1975      socketOutput.writeUTF(catalog);
1976      socketOutput.writeUTF(schemaPattern);
1977      socketOutput.writeUTF(tableNamePattern);
1978      socketOutput.writeUTF(columnNamePattern);
1979      socketOutput.flush();
1980
1981      if (cjdbcUrl.isDebugEnabled())
1982        System.out.println(myName + "(" + catalog + "," + schemaPattern + ","
1983            + tableNamePattern + "," + columnNamePattern + ")");
1984
1985      return receiveResultSet(myName);
1986    }
1987    catch (SerializableException e)
1988    {
1989      throw new DriverSQLException(e);
1990    }
1991    catch (IOException JavaDoc e)
1992    {
1993      throw wrapIOExceptionInDriverSQLException("getColumns", e);
1994    }
1995  }
1996
1997  /**
1998   * @see java.sql.DatabaseMetaData#getCrossReference(java.lang.String,
1999   * java.lang.String, java.lang.String, java.lang.String,
2000   * java.lang.String, java.lang.String)
2001   */

2002  protected synchronized ResultSet JavaDoc getCrossReference(String JavaDoc primaryCatalog,
2003      String JavaDoc primarySchema, String JavaDoc primaryTable, String JavaDoc foreignCatalog,
2004      String JavaDoc foreignSchema, String JavaDoc foreignTable) throws DriverSQLException
2005  {
2006    throwSQLExceptionIfClosed();
2007    String JavaDoc myName = "Connection.getCrossReference";
2008    try
2009    {
2010      socketOutput.writeInt(Commands.DatabaseMetaDataGetCrossReference);
2011      socketOutput.writeUTF(primaryCatalog);
2012      socketOutput.writeUTF(primarySchema);
2013      socketOutput.writeUTF(primaryTable);
2014      socketOutput.writeUTF(foreignCatalog);
2015      socketOutput.writeUTF(foreignSchema);
2016      socketOutput.writeUTF(foreignTable);
2017      socketOutput.flush();
2018
2019      if (cjdbcUrl.isDebugEnabled())
2020        System.out.println(myName + "(" + primaryCatalog + "," + primarySchema
2021            + "," + primaryTable + "," + foreignCatalog + "," + foreignSchema
2022            + "," + foreignTable + ")");
2023
2024      return receiveResultSet(myName);
2025    }
2026    catch (SerializableException e)
2027    {
2028      throw new DriverSQLException(e);
2029    }
2030    catch (IOException JavaDoc e)
2031    {
2032      throw wrapIOExceptionInDriverSQLException("getCrossReference", e);
2033    }
2034  }
2035
2036  /**
2037   * @see java.sql.DatabaseMetaData#getExportedKeys(java.lang.String,
2038   * java.lang.String, java.lang.String)
2039   */

2040  public ResultSet JavaDoc getExportedKeys(String JavaDoc catalog, String JavaDoc schema, String JavaDoc table)
2041      throws DriverSQLException
2042  {
2043    throwSQLExceptionIfClosed();
2044    String JavaDoc myName = "Connection.getExportedKeys";
2045    try
2046    {
2047      socketOutput.writeInt(Commands.DatabaseMetaDataGetExportedKeys);
2048      socketOutput.writeUTF(catalog);
2049      socketOutput.writeUTF(schema);
2050      socketOutput.writeUTF(table);
2051      socketOutput.flush();
2052
2053      if (cjdbcUrl.isDebugEnabled())
2054        System.out.println(myName + "(" + catalog + "," + schema + "," + table
2055            + ")");
2056
2057      return receiveResultSet(myName);
2058    }
2059    catch (SerializableException e)
2060    {
2061      throw new DriverSQLException(e);
2062    }
2063    catch (IOException JavaDoc e)
2064    {
2065      throw wrapIOExceptionInDriverSQLException("getExportedKeys", e);
2066    }
2067  }
2068
2069  /**
2070   * @see java.sql.DatabaseMetaData#getImportedKeys(java.lang.String,
2071   * java.lang.String, java.lang.String)
2072   */

2073  protected synchronized ResultSet JavaDoc getImportedKeys(String JavaDoc catalog,
2074      String JavaDoc schema, String JavaDoc table) throws DriverSQLException
2075  {
2076    throwSQLExceptionIfClosed();
2077    String JavaDoc myName = "Connection.getImportedKeys";
2078    try
2079    {
2080      socketOutput.writeInt(Commands.DatabaseMetaDataGetImportedKeys);
2081      socketOutput.writeUTF(catalog);
2082      socketOutput.writeUTF(schema);
2083      socketOutput.writeUTF(table);
2084      socketOutput.flush();
2085
2086      if (cjdbcUrl.isDebugEnabled())
2087        System.out.println(myName + "(" + catalog + "," + schema + "," + table
2088            + ")");
2089
2090      return receiveResultSet(myName);
2091    }
2092    catch (SerializableException e)
2093    {
2094      throw new DriverSQLException(e);
2095    }
2096    catch (IOException JavaDoc e)
2097    {
2098      throw wrapIOExceptionInDriverSQLException("getImportedKeys", e);
2099    }
2100  }
2101
2102  /**
2103   * @see java.sql.DatabaseMetaData#getIndexInfo(java.lang.String,
2104   * java.lang.String, java.lang.String, boolean, boolean)
2105   */

2106  protected synchronized ResultSet JavaDoc getIndexInfo(String JavaDoc catalog, String JavaDoc schema,
2107      String JavaDoc table, boolean unique, boolean approximate)
2108      throws DriverSQLException
2109  {
2110    throwSQLExceptionIfClosed();
2111    String JavaDoc myName = "Connection.getIndexInfo";
2112    try
2113    {
2114      socketOutput.writeInt(Commands.DatabaseMetaDataGetIndexInfo);
2115      socketOutput.writeUTF(catalog);
2116      socketOutput.writeUTF(schema);
2117      socketOutput.writeUTF(table);
2118      socketOutput.writeBoolean(unique);
2119      socketOutput.writeBoolean(approximate);
2120      socketOutput.flush();
2121
2122      if (cjdbcUrl.isDebugEnabled())
2123        System.out.println(myName + "(" + catalog + "," + schema + "," + table
2124            + "," + unique + "," + approximate + ")");
2125
2126      return receiveResultSet(myName);
2127    }
2128    catch (SerializableException e)
2129    {
2130      throw new DriverSQLException(e);
2131    }
2132    catch (IOException JavaDoc e)
2133    {
2134      throw wrapIOExceptionInDriverSQLException("getIndexInfo", e);
2135    }
2136  }
2137
2138  /**
2139   * @see java.sql.DatabaseMetaData#getPrimaryKeys(java.lang.String,
2140   * java.lang.String, java.lang.String)
2141   */

2142  protected synchronized ResultSet JavaDoc getPrimaryKeys(String JavaDoc catalog,
2143      String JavaDoc schemaPattern, String JavaDoc tableNamePattern) throws DriverSQLException
2144  {
2145    throwSQLExceptionIfClosed();
2146    String JavaDoc myName = "Connection.getPrimaryKeys";
2147    try
2148    {
2149      socketOutput.writeInt(Commands.DatabaseMetaDataGetPrimaryKeys);
2150      socketOutput.writeUTF(catalog);
2151      socketOutput.writeUTF(schemaPattern);
2152      socketOutput.writeUTF(tableNamePattern);
2153      socketOutput.flush();
2154
2155      if (cjdbcUrl.isDebugEnabled())
2156        System.out.println(myName + "(" + catalog + "," + schemaPattern + ","
2157            + tableNamePattern + ")");
2158
2159      return receiveResultSet(myName);
2160    }
2161    catch (SerializableException e)
2162    {
2163      throw new DriverSQLException(e);
2164    }
2165    catch (IOException JavaDoc e)
2166    {
2167      throw wrapIOExceptionInDriverSQLException("getPrimaryKeys", e);
2168    }
2169  }
2170
2171  /**
2172   * @see java.sql.DatabaseMetaData#getSuperTables(java.lang.String,
2173   * java.lang.String, java.lang.String)
2174   */

2175  protected synchronized ResultSet JavaDoc getSuperTables(String JavaDoc catalog,
2176      String JavaDoc schemaPattern, String JavaDoc tableNamePattern) throws DriverSQLException
2177  {
2178    throwSQLExceptionIfClosed();
2179    String JavaDoc myName = "Connection.getSuperTables";
2180    try
2181    {
2182      socketOutput.writeInt(Commands.DatabaseMetaDataGetSuperTables);
2183      socketOutput.writeUTF(catalog);
2184      socketOutput.writeUTF(schemaPattern);
2185      socketOutput.writeUTF(tableNamePattern);
2186      socketOutput.flush();
2187
2188      if (cjdbcUrl.isDebugEnabled())
2189        System.out.println(myName + "(" + catalog + "," + schemaPattern + ","
2190            + tableNamePattern + ")");
2191
2192      return receiveResultSet(myName);
2193    }
2194    catch (SerializableException e)
2195    {
2196      throw new DriverSQLException(e);
2197    }
2198    catch (IOException JavaDoc e)
2199    {
2200      throw wrapIOExceptionInDriverSQLException("getSuperTables", e);
2201    }
2202  }
2203
2204  /**
2205   * @see java.sql.DatabaseMetaData#getSuperTypes(java.lang.String,
2206   * java.lang.String, java.lang.String)
2207   */

2208  protected synchronized ResultSet JavaDoc getSuperTypes(String JavaDoc catalog,
2209      String JavaDoc schemaPattern, String JavaDoc typeNamePattern) throws DriverSQLException
2210  {
2211    throwSQLExceptionIfClosed();
2212    String JavaDoc myName = "Connection.getSuperTypes";
2213    try
2214    {
2215      socketOutput.writeInt(Commands.DatabaseMetaDataGetSuperTypes);
2216      socketOutput.writeUTF(catalog);
2217      socketOutput.writeUTF(schemaPattern);
2218      socketOutput.writeUTF(typeNamePattern);
2219      socketOutput.flush();
2220
2221      if (cjdbcUrl.isDebugEnabled())
2222        System.out.println(myName + "(" + catalog + "," + schemaPattern + ","
2223            + typeNamePattern + ")");
2224
2225      return receiveResultSet(myName);
2226    }
2227    catch (SerializableException e)
2228    {
2229      throw new DriverSQLException(e);
2230    }
2231    catch (IOException JavaDoc e)
2232    {
2233      throw wrapIOExceptionInDriverSQLException("getSuperTypes", e);
2234    }
2235  }
2236
2237  /**
2238   * @see org.objectweb.cjdbc.driver.DatabaseMetaData#getTables(String, String,
2239   * String, String[])
2240   */

2241  protected synchronized ResultSet JavaDoc getTables(String JavaDoc catalog,
2242      String JavaDoc schemaPattern, String JavaDoc tableNamePattern, String JavaDoc[] types)
2243      throws DriverSQLException
2244  {
2245    throwSQLExceptionIfClosed();
2246    String JavaDoc myName = "Connection.getTables";
2247    try
2248    {
2249      socketOutput.writeInt(Commands.DatabaseMetaDataGetTables);
2250      socketOutput.writeUTF(catalog);
2251      socketOutput.writeUTF(schemaPattern);
2252      socketOutput.writeUTF(tableNamePattern);
2253
2254      if (null == types)
2255        socketOutput.writeBoolean(false);
2256      else
2257      {
2258        socketOutput.writeBoolean(true);
2259        socketOutput.writeInt(types.length);
2260        for (int i = 0; i < types.length; i++)
2261          socketOutput.writeUTF(types[i]);
2262      }
2263      socketOutput.flush();
2264
2265      if (cjdbcUrl.isDebugEnabled())
2266        System.out.println(myName + "(" + catalog + "," + schemaPattern + ","
2267            + tableNamePattern + "," + types + ")");
2268
2269      return receiveResultSet(myName);
2270    }
2271    catch (SerializableException e)
2272    {
2273      throw new DriverSQLException(e);
2274    }
2275    catch (IOException JavaDoc e)
2276    {
2277      throw wrapIOExceptionInDriverSQLException("getTables", e);
2278    }
2279  }
2280
2281  /**
2282   * @see java.sql.DatabaseMetaData#getTypeInfo()
2283   */

2284  protected synchronized ResultSet JavaDoc getTypeInfo() throws DriverSQLException
2285  {
2286    throwSQLExceptionIfClosed();
2287    String JavaDoc myName = "Connection.getTypeInfo";
2288    try
2289    {
2290      socketOutput.writeInt(Commands.DatabaseMetaDataGetTypeInfo);
2291      socketOutput.flush();
2292
2293      if (cjdbcUrl.isDebugEnabled())
2294        System.out.println(myName + "()");
2295
2296      return receiveResultSet(myName);
2297    }
2298    catch (SerializableException e)
2299    {
2300      throw new DriverSQLException(e);
2301    }
2302    catch (IOException JavaDoc e)
2303    {
2304      throw wrapIOExceptionInDriverSQLException("getTypeInfo", e);
2305    }
2306  }
2307
2308  /**
2309   * @see java.sql.DatabaseMetaData#getUDTs(java.lang.String, java.lang.String,
2310   * java.lang.String, int[])
2311   */

2312  protected synchronized ResultSet JavaDoc getUDTs(String JavaDoc catalog,
2313      String JavaDoc schemaPattern, String JavaDoc typeNamePattern, int[] types)
2314      throws DriverSQLException
2315  {
2316    throwSQLExceptionIfClosed();
2317    String JavaDoc myName = "Connection.getUDTs";
2318    try
2319    {
2320      socketOutput.writeInt(Commands.DatabaseMetaDataGetUDTs);
2321      socketOutput.writeUTF(catalog);
2322      socketOutput.writeUTF(schemaPattern);
2323      socketOutput.writeUTF(typeNamePattern);
2324
2325      if (null == types)
2326        socketOutput.writeBoolean(false);
2327      else
2328      {
2329        socketOutput.writeBoolean(true);
2330        socketOutput.writeInt(types.length);
2331        for (int i = 0; i < types.length; i++)
2332          socketOutput.writeInt(types[i]);
2333      }
2334      socketOutput.flush();
2335
2336      if (cjdbcUrl.isDebugEnabled())
2337        System.out.println(myName + "(" + catalog + "," + schemaPattern + ","
2338            + typeNamePattern + "," + types + ")");
2339
2340      return receiveResultSet(myName);
2341    }
2342    catch (SerializableException e)
2343    {
2344      throw new DriverSQLException(e);
2345    }
2346    catch (IOException JavaDoc e)
2347    {
2348      throw wrapIOExceptionInDriverSQLException("getUDTs", e);
2349    }
2350  }
2351
2352  /**
2353   * @see java.sql.DatabaseMetaData#getVersionColumns(java.lang.String,
2354   * java.lang.String, java.lang.String)
2355   */

2356  public synchronized ResultSet JavaDoc getVersionColumns(String JavaDoc catalog,
2357      String JavaDoc schema, String JavaDoc table) throws DriverSQLException
2358  {
2359    throwSQLExceptionIfClosed();
2360    String JavaDoc myName = "Connection.getVersionColumns";
2361    try
2362    {
2363      socketOutput.writeInt(Commands.DatabaseMetaDataGetVersionColumns);
2364      socketOutput.writeUTF(catalog);
2365      socketOutput.writeUTF(schema);
2366      socketOutput.writeUTF(table);
2367      socketOutput.flush();
2368
2369      if (cjdbcUrl.isDebugEnabled())
2370        System.out.println(myName + "(" + catalog + "," + schema + "," + table
2371            + ")");
2372
2373      return receiveResultSet(myName);
2374    }
2375    catch (SerializableException e)
2376    {
2377      throw new DriverSQLException(e);
2378    }
2379    catch (IOException JavaDoc e)
2380    {
2381      throw wrapIOExceptionInDriverSQLException("getVersionColumns", e);
2382    }
2383  }
2384
2385  /**
2386   * Retrieve a static metadata from the controller.
2387   *
2388   * @param key the "getXXX(Y,Z,...)" hash key of the metadata query
2389   * @return an Object that will be an <tt>Integer</tt> or <tt>Boolean</tt>
2390   * or <tt>String</tt>
2391   * @throws DriverSQLException if fails
2392   * @see org.objectweb.cjdbc.controller.virtualdatabase.VirtualDatabaseWorkerThread#databaseStaticMetadata()
2393   * @see org.objectweb.cjdbc.controller.backend.DatabaseBackendMetaData#retrieveDatabaseMetadata()
2394   */

2395  synchronized Object JavaDoc getStaticMetadata(String JavaDoc key) throws DriverSQLException
2396  {
2397    throwSQLExceptionIfClosed();
2398    try
2399    {
2400      socketOutput.writeInt(Commands.DatabaseStaticMetadata);
2401      socketOutput.writeUTF(key);
2402      socketOutput.flush();
2403      if (cjdbcUrl.isDebugEnabled())
2404        System.out.println("Getting " + key + " metadata");
2405
2406      TypeTag tag = new TypeTag(socketInput);
2407
2408      if (TypeTag.EXCEPTION.equals(tag))
2409        throw new DriverSQLException(receiveException());
2410      else
2411      {
2412        tag = new TypeTag(socketInput);
2413        Object JavaDoc result = SQLDataSerialization.getSerializer(tag)
2414            .receiveFromStream(socketInput);
2415        return result;
2416      }
2417    }
2418    catch (NotImplementedException nie)
2419    {
2420      throw new DriverSQLException("Internal bug: getSerializer failed"
2421          + " in getStaticMetadata", nie);
2422    }
2423    catch (IOException JavaDoc e)
2424    {
2425      throw wrapIOExceptionInDriverSQLException("getStaticMetadata", e);
2426    }
2427  }
2428
2429  private DriverSQLException wrapIOExceptionInDriverSQLException(
2430      String JavaDoc callerName, IOException JavaDoc ioe)
2431  {
2432    return new DriverSQLException("I/O Error on method " + callerName + "():\n"
2433        + ioe.getLocalizedMessage(), ioe);
2434  }
2435
2436  /**
2437   * Get the C-JDBC controller version number.
2438   *
2439   * @return a String containing the controller version
2440   * @exception DriverSQLException if an error occurs
2441   */

2442  public synchronized String JavaDoc getControllerVersionNumber()
2443      throws DriverSQLException
2444  {
2445    throwSQLExceptionIfClosed();
2446    try
2447    {
2448      socketOutput.writeInt(Commands.GetControllerVersionNumber);
2449      socketOutput.flush();
2450
2451      if (cjdbcUrl.isDebugEnabled())
2452        System.out.println("Connection.getControllerVersionNumber()");
2453
2454      return receiveString();
2455    }
2456    catch (SerializableException e)
2457    {
2458      throw new DriverSQLException(e);
2459    }
2460    catch (IOException JavaDoc e)
2461    {
2462      throw wrapIOExceptionInDriverSQLException("getControllerVersionNumber", e);
2463    }
2464  }
2465
2466  // --------------------------JDBC 3.0-----------------------------
2467

2468  /**
2469   * Changes the holdability of <code>ResultSet</code> objects created using
2470   * this <code>Connection</code> object to the given holdability.
2471   *
2472   * @param holdability a <code>ResultSet</code> holdability constant; one of
2473   * <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
2474   * <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
2475   * @throws SQLException if a database access occurs, the given parameter is
2476   * not a <code>ResultSet</code> constant indicating holdability,
2477   * or the given holdability is not supported
2478   * @see #getHoldability
2479   * @see ResultSet
2480   * @since JDK 1.4
2481   */

2482  public void setHoldability(int holdability) throws SQLException JavaDoc
2483  {
2484    throw new NotImplementedException("setHoldability");
2485  }
2486
2487  /**
2488   * Retrieves the current holdability of <code>ResultSet</code> objects
2489   * created using this <code>Connection</code> object.
2490   *
2491   * @return the holdability, one of
2492   * <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
2493   * <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
2494   * @throws SQLException if a database access occurs
2495   * @see #setHoldability
2496   * @see ResultSet
2497   * @since JDK 1.4
2498   */

2499  public int getHoldability() throws SQLException JavaDoc
2500  {
2501    throw new NotImplementedException("getHoldability");
2502  }
2503
2504  /**
2505   * Creates an unnamed savepoint in the current transaction and returns the new
2506   * <code>Savepoint</code> object that represents it.
2507   *
2508   * @return the new <code>Savepoint</code> object
2509   * @exception DriverSQLException if a database access error occurs or this
2510   * <code>Connection</code> object is currently in auto-commit
2511   * mode
2512   * @see Savepoint
2513   * @since JDK 1.4
2514   */

2515  public Savepoint setSavepoint() throws DriverSQLException
2516  {
2517    throwSQLExceptionIfClosed();
2518    if (autoCommit)
2519      throw new DriverSQLException(
2520          "Trying to set a savepoint in autocommit mode");
2521
2522    if (driver == null)
2523      throw new DriverSQLException("No driver to set a savepoint");
2524
2525    try
2526    {
2527      socketOutput.writeInt(Commands.SetUnnamedSavepoint);
2528      socketOutput.flush();
2529
2530      int savepointId = receiveInt();
2531      return new org.objectweb.cjdbc.driver.Savepoint(savepointId);
2532    }
2533    catch (SerializableException e)
2534    {
2535      throw new DriverSQLException(e);
2536    }
2537    catch (IOException JavaDoc ioe)
2538    {
2539      throw wrapIOExceptionInDriverSQLException("setSavePoint", ioe);
2540    }
2541  }
2542
2543  /**
2544   * Creates a savepoint with the given name in the current transaction and
2545   * returns the new <code>Savepoint</code> object that represents it.
2546   *
2547   * @param name a <code>String</code> containing the name of the savepoint
2548   * @return the new <code>Savepoint</code> object
2549   * @exception DriverSQLException if a database access error occurs or this
2550   * <code>Connection</code> object is currently in auto-commit
2551   * mode
2552   * @see Savepoint
2553   * @since JDK 1.4
2554   */

2555  public Savepoint setSavepoint(String JavaDoc name) throws DriverSQLException
2556  {
2557    throwSQLExceptionIfClosed();
2558    if (name == null)
2559      throw new IllegalArgumentException JavaDoc("Savepoint name cannot be null");
2560
2561    if (autoCommit)
2562      throw new DriverSQLException(
2563          "Trying to set a savepoint in autocommit mode");
2564
2565    if (driver == null)
2566      throw new DriverSQLException("No driver to set a savepoint");
2567
2568    try
2569    {
2570      socketOutput.writeInt(Commands.SetNamedSavepoint);
2571      socketOutput.writeUTF(name);
2572      socketOutput.flush();
2573
2574      this.receiveBoolean();
2575      return new org.objectweb.cjdbc.driver.Savepoint(name);
2576    }
2577    catch (SerializableException se)
2578    {
2579      throw new DriverSQLException(se);
2580    }
2581    catch (IOException JavaDoc e)
2582    {
2583      throw wrapIOExceptionInDriverSQLException("setSavePoint", e);
2584    }
2585  }
2586
2587  /**
2588   * Undoes all changes made after the given <code>Savepoint</code> object was
2589   * set.
2590   * <p>
2591   * This method should be used only when auto-commit has been disabled.
2592   *
2593   * @param savepoint the <code>Savepoint</code> object to roll back to
2594   * @exception DriverSQLException if a database access error occurs, the
2595   * <code>Savepoint</code> object is no longer valid, or this
2596   * <code>Connection</code> object is currently in auto-commit
2597   * mode
2598   * @see Savepoint
2599   * @see #rollback()
2600   * @since JDK 1.4
2601   */

2602  public void rollback(Savepoint savepoint) throws DriverSQLException
2603  {
2604    throwSQLExceptionIfClosed();
2605    if (savepoint == null)
2606      throw new IllegalArgumentException JavaDoc("Savepoint cannot be null");
2607
2608    if (autoCommit)
2609      throw new DriverSQLException(
2610          "Trying to release a savepoint in autocommit mode");
2611
2612    if (driver == null)
2613      throw new DriverSQLException("No driver to release a savepoint");
2614
2615    try
2616    {
2617      socketOutput.writeInt(Commands.RollbackToSavepoint);
2618      savepointOnStream(savepoint);
2619      socketOutput.flush();
2620
2621      this.receiveBoolean();
2622    }
2623    catch (SerializableException e)
2624    {
2625      throw new DriverSQLException(e);
2626    }
2627    catch (IOException JavaDoc e)
2628    {
2629      throw wrapIOExceptionInDriverSQLException("(savepoint) rollback", e);
2630    }
2631  }
2632
2633  /**
2634   * Removes the given <code>Savepoint</code> object from the current
2635   * transaction. Any reference to the savepoint after it have been removed will
2636   * cause an <code>SQLException</code> to be thrown.
2637   *
2638   * @param savepoint the <code>Savepoint</code> object to be removed
2639   * @exception DriverSQLException if a database access error occurs or the
2640   * given <code>Savepoint</code> object is not a valid savepoint
2641   * in the current transaction
2642   * @since JDK 1.4
2643   */

2644  public void releaseSavepoint(Savepoint savepoint) throws DriverSQLException
2645  {
2646    throwSQLExceptionIfClosed();
2647    if (savepoint == null)
2648      throw new IllegalArgumentException JavaDoc("Savepoint cannot be null");
2649
2650    if (autoCommit)
2651      throw new DriverSQLException(
2652          "Trying to release a savepoint in autocommit mode");
2653
2654    if (driver == null)
2655      throw new DriverSQLException("No driver to release a savepoint");
2656
2657    try
2658    {
2659      socketOutput.writeInt(Commands.ReleaseSavepoint);
2660      savepointOnStream(savepoint);
2661      socketOutput.flush();
2662
2663      this.receiveBoolean();
2664    }
2665    catch (SerializableException e)
2666    {
2667      throw new DriverSQLException(e);
2668    }
2669    catch (IOException JavaDoc e)
2670    {
2671      throw wrapIOExceptionInDriverSQLException("releaseSavepoint", e);
2672    }
2673  }
2674
2675  /**
2676   * Creates a <code>Statement</code> object that will generate
2677   * <code>ResultSet</code> objects with the given type, concurrency, and
2678   * holdability.
2679   * <p>
2680   * This method is the same as the <code>createStatement</code> method above,
2681   * but it allows the default result set type, concurrency, and holdability to
2682   * be overridden.
2683   *
2684   * @param resultSetType one of the following <code>ResultSet</code>
2685   * constants: <code>ResultSet.TYPE_FORWARD_ONLY</code>,
2686   * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
2687   * <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
2688   * @param resultSetConcurrency one of the following <code>ResultSet</code>
2689   * constants: <code>ResultSet.CONCUR_READ_ONLY</code> or
2690   * <code>ResultSet.CONCUR_UPDATABLE</code>
2691   * @param resultSetHoldability one of the following <code>ResultSet</code>
2692   * constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
2693   * <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
2694   * @return a new <code>Statement</code> object that will generate
2695   * <code>ResultSet</code> objects with the given type, concurrency,
2696   * and holdability
2697   * @exception SQLException if a database access error occurs or the given
2698   * parameters are not <code>ResultSet</code> constants
2699   * indicating type, concurrency, and holdability
2700   * @see ResultSet
2701   * @since JDK 1.4
2702   */

2703  public java.sql.Statement JavaDoc createStatement(int resultSetType,
2704      int resultSetConcurrency, int resultSetHoldability) throws SQLException JavaDoc
2705  {
2706    throw new NotImplementedException("createStatement");
2707  }
2708
2709  /**
2710   * Creates a <code>PreparedStatement</code> object that will generate
2711   * <code>ResultSet</code> objects with the given type, concurrency, and
2712   * holdability.
2713   * <p>
2714   * This method is the same as the <code>prepareStatement</code> method
2715   * above, but it allows the default result set type, concurrency, and
2716   * holdability to be overridden.
2717   *
2718   * @param sql a <code>String</code> object that is the SQL statement to be
2719   * sent to the database; may contain one or more ? IN parameters
2720   * @param resultSetType one of the following <code>ResultSet</code>
2721   * constants: <code>ResultSet.TYPE_FORWARD_ONLY</code>,
2722   * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
2723   * <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
2724   * @param resultSetConcurrency one of the following <code>ResultSet</code>
2725   * constants: <code>ResultSet.CONCUR_READ_ONLY</code> or
2726   * <code>ResultSet.CONCUR_UPDATABLE</code>
2727   * @param resultSetHoldability one of the following <code>ResultSet</code>
2728   * constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
2729   * <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
2730   * @return a new <code>PreparedStatement</code> object, containing the
2731   * pre-compiled SQL statement, that will generate
2732   * <code>ResultSet</code> objects with the given type, concurrency,
2733   * and holdability
2734   * @exception SQLException if a database access error occurs or the given
2735   * parameters are not <code>ResultSet</code> constants
2736   * indicating type, concurrency, and holdability
2737   * @see ResultSet
2738   * @since JDK 1.4
2739   */

2740  public java.sql.PreparedStatement JavaDoc prepareStatement(String JavaDoc sql,
2741      int resultSetType, int resultSetConcurrency, int resultSetHoldability)
2742      throws SQLException JavaDoc
2743  {
2744    throw new NotImplementedException("prepareStatement");
2745  }
2746
2747  /**
2748   * Creates a <code>CallableStatement</code> object that will generate
2749   * <code>ResultSet</code> objects with the given type and concurrency. This
2750   * method is the same as the <code>prepareCall</code> method above, but it
2751   * allows the default result set type, result set concurrency type and
2752   * holdability to be overridden.
2753   *
2754   * @param sql a <code>String</code> object that is the SQL statement to be
2755   * sent to the database; may contain on or more ? parameters
2756   * @param resultSetType one of the following <code>ResultSet</code>
2757   * constants: <code>ResultSet.TYPE_FORWARD_ONLY</code>,
2758   * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
2759   * <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
2760   * @param resultSetConcurrency one of the following <code>ResultSet</code>
2761   * constants: <code>ResultSet.CONCUR_READ_ONLY</code> or
2762   * <code>ResultSet.CONCUR_UPDATABLE</code>
2763   * @param resultSetHoldability one of the following <code>ResultSet</code>
2764   * constants: <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
2765   * <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
2766   * @return a new <code>CallableStatement</code> object, containing the
2767   * pre-compiled SQL statement, that will generate
2768   * <code>ResultSet</code> objects with the given type, concurrency,
2769   * and holdability
2770   * @exception SQLException if a database access error occurs or the given
2771   * parameters are not <code>ResultSet</code> constants
2772   * indicating type, concurrency, and holdability
2773   * @see ResultSet
2774   * @since JDK 1.4
2775   */

2776  public java.sql.CallableStatement JavaDoc prepareCall(String JavaDoc sql, int resultSetType,
2777      int resultSetConcurrency, int resultSetHoldability) throws SQLException JavaDoc
2778  {
2779    throw new NotImplementedException("prepareCall");
2780  }
2781
2782  /**
2783   * Creates a default <code>PreparedStatement</code> object that has the
2784   * capability to retrieve auto-generated keys. The given constant tells the
2785   * driver whether it should make auto-generated keys available for retrieval.
2786   * This parameter is ignored if the SQL statement is not an
2787   * <code>INSERT</code> statement.
2788   * <p>
2789   * <b>Note: </b> This method is optimized for handling parametric SQL
2790   * statements that benefit from precompilation. If the driver supports
2791   * precompilation, the method <code>prepareStatement</code> will send the
2792   * statement to the database for precompilation. Some drivers may not support
2793   * precompilation. In this case, the statement may not be sent to the database
2794   * until the <code>PreparedStatement</code> object is executed. This has no
2795   * direct effect on users; however, it does affect which methods throw certain
2796   * SQLExceptions.
2797   * <p>
2798   * Result sets created using the returned <code>PreparedStatement</code>
2799   * object will by default be type <code>TYPE_FORWARD_ONLY</code> and have a
2800   * concurrency level of <code>CONCUR_READ_ONLY</code>.
2801   *
2802   * @param sql an SQL statement that may contain one or more '?' IN parameter
2803   * placeholders
2804   * @param autoGeneratedKeys a flag indicating whether auto-generated keys
2805   * should be returned; one of
2806   * <code>Statement.RETURN_GENERATED_KEYS</code> or
2807   * <code>Statement.NO_GENERATED_KEYS</code>
2808   * @return a new <code>PreparedStatement</code> object, containing the
2809   * pre-compiled SQL statement, that will have the capability of
2810   * returning auto-generated keys
2811   * @exception SQLException if a database access error occurs or the given
2812   * parameter is not a <code>Statement</code> constant
2813   * indicating whether auto-generated keys should be returned
2814   * @since JDK 1.4
2815   */

2816  public java.sql.PreparedStatement JavaDoc prepareStatement(String JavaDoc sql,
2817      int autoGeneratedKeys) throws SQLException JavaDoc
2818  {
2819    throwSQLExceptionIfClosed();
2820    PreparedStatement ps = new PreparedStatement(this, sql);
2821    ps.setGeneratedKeysFlag(autoGeneratedKeys);
2822    return ps;
2823  }
2824
2825  /**
2826   * Creates a default <code>PreparedStatement</code> object capable of
2827   * returning the auto-generated keys designated by the given array. This array
2828   * contains the indexes of the columns in the target table that contain the
2829   * auto-generated keys that should be made available. This array is ignored if
2830   * the SQL statement is not an <code>INSERT</code> statement.
2831   * <p>
2832   * An SQL statement with or without IN parameters can be pre-compiled and
2833   * stored in a <code>PreparedStatement</code> object. This object can then
2834   * be used to efficiently execute this statement multiple times.
2835   * <p>
2836   * <b>Note: </b> This method is optimized for handling parametric SQL
2837   * statements that benefit from precompilation. If the driver supports
2838   * precompilation, the method <code>prepareStatement</code> will send the
2839   * statement to the database for precompilation. Some drivers may not support
2840   * precompilation. In this case, the statement may not be sent to the database
2841   * until the <code>PreparedStatement</code> object is executed. This has no
2842   * direct effect on users; however, it does affect which methods throw certain
2843   * SQLExceptions.
2844   * <p>
2845   * Result sets created using the returned <code>PreparedStatement</code>
2846   * object will by default be type <code>TYPE_FORWARD_ONLY</code> and have a
2847   * concurrency level of <code>CONCUR_READ_ONLY</code>.
2848   *
2849   * @param sql an SQL statement that may contain one or more '?' IN parameter
2850   * placeholders
2851   * @param columnIndexes an array of column indexes indicating the columns that
2852   * should be returned from the inserted row or rows
2853   * @return a new <code>PreparedStatement</code> object, containing the
2854   * pre-compiled statement, that is capable of returning the
2855   * auto-generated keys designated by the given array of column indexes
2856   * @exception SQLException if a database access error occurs
2857   * @since JDK 1.4
2858   */

2859  public java.sql.PreparedStatement JavaDoc prepareStatement(String JavaDoc sql,
2860      int[] columnIndexes) throws SQLException JavaDoc
2861  {
2862    throw new NotImplementedException("prepareStatement");
2863  }
2864
2865  /**
2866   * Creates a default <code>PreparedStatement</code> object capable of
2867   * returning the auto-generated keys designated by the given array. This array
2868   * contains the names of the columns in the target table that contain the
2869   * auto-generated keys that should be returned. This array is ignored if the
2870   * SQL statement is not an <code>INSERT</code> statement.
2871   * <p>
2872   * An SQL statement with or without IN parameters can be pre-compiled and
2873   * stored in a <code>PreparedStatement</code> object. This object can then
2874   * be used to efficiently execute this statement multiple times.
2875   * <p>
2876   * <b>Note: </b> This method is optimized for handling parametric SQL
2877   * statements that benefit from precompilation. If the driver supports
2878   * precompilation, the method <code>prepareStatement</code> will send the
2879   * statement to the database for precompilation. Some drivers may not support
2880   * precompilation. In this case, the statement may not be sent to the database
2881   * until the <code>PreparedStatement</code> object is executed. This has no
2882   * direct effect on users; however, it does affect which methods throw certain
2883   * <code>SQLExceptions</code>.
2884   * <p>
2885   * Result sets created using the returned <code>PreparedStatement</code>
2886   * object will by default be type <code>TYPE_FORWARD_ONLY</code> and have a
2887   * concurrency level of <code>CONCUR_READ_ONLY</code>.
2888   *
2889   * @param sql an SQL statement that may contain one or more '?' IN parameter
2890   * placeholders
2891   * @param columnNames an array of column names indicating the columns that
2892   * should be returned from the inserted row or rows
2893   * @return a new <code>PreparedStatement</code> object, containing the
2894   * pre-compiled statement, that is capable of returning the
2895   * auto-generated keys designated by the given array of column names
2896   * @exception SQLException if a database access error occurs
2897   * @since JDK 1.4
2898   */

2899  public java.sql.PreparedStatement JavaDoc prepareStatement(String JavaDoc sql,
2900      String JavaDoc[] columnNames) throws SQLException JavaDoc
2901  {
2902    throw new NotImplementedException("prepareStatement");
2903  }
2904
2905  /**
2906   * Gets the table types available in this database. The results are ordered by
2907   * table type.
2908   *
2909   * @return <code>ResultSet</code> each row has a single String column that
2910   * is a catalog name
2911   * @throws SQLException if a database error occurs
2912   */

2913  public synchronized ResultSet JavaDoc getTableTypes() throws SQLException JavaDoc
2914  {
2915    throwSQLExceptionIfClosed();
2916    String JavaDoc myName = "Connection.getTableTypes";
2917    try
2918    {
2919      socketOutput.writeInt(Commands.DatabaseMetaDataGetTableTypes);
2920      socketOutput.flush();
2921
2922      if (cjdbcUrl.isDebugEnabled())
2923        System.out.println(myName);
2924
2925      return receiveResultSet(myName);
2926    }
2927    catch (SerializableException e)
2928    {
2929      throw new DriverSQLException(e);
2930    }
2931    catch (IOException JavaDoc e)
2932    {
2933      throw wrapIOExceptionInDriverSQLException("getTableTypes", e);
2934    }
2935  }
2936
2937  /**
2938   * Gets a description of the access rights for each table available in a
2939   * catalog. Note that a table privilege applies to one or more columns in the
2940   * table. It would be wrong to assume that this priviledge applies to all
2941   * columns (this may be true for some systems but is not true for all.) Only
2942   * privileges matching the schema and table name criteria are returned. They
2943   * are ordered by TABLE_SCHEM, TABLE_NAME, and PRIVILEGE.
2944   *
2945   * @param catalog a catalog name; "" retrieves those without a catalog; null
2946   * means drop catalog name from the selection criteria
2947   * @param schemaPattern a schema name pattern; "" retrieves those without a
2948   * schema
2949   * @param tableNamePattern a table name pattern
2950   * @return <code>ResultSet</code> each row is a table privilege description
2951   * @throws DriverSQLException if a database access error occurs
2952   */

2953  public synchronized ResultSet JavaDoc getTablePrivileges(String JavaDoc catalog,
2954      String JavaDoc schemaPattern, String JavaDoc tableNamePattern) throws DriverSQLException
2955  {
2956    throwSQLExceptionIfClosed();
2957    String JavaDoc myName = "Connection.getTablePrivileges";
2958    try
2959    {
2960      socketOutput.writeInt(Commands.DatabaseMetaDataGetTablePrivileges);
2961      socketOutput.writeUTF(catalog);
2962      socketOutput.writeUTF(schemaPattern);
2963      socketOutput.writeUTF(tableNamePattern);
2964      socketOutput.flush();
2965
2966      if (cjdbcUrl.isDebugEnabled())
2967        System.out.println(myName + "(" + catalog + "," + schemaPattern + ","
2968            + tableNamePattern + ")");
2969
2970      return receiveResultSet(myName);
2971    }
2972    catch (SerializableException e)
2973    {
2974      throw new DriverSQLException(e);
2975    }
2976    catch (IOException JavaDoc e)
2977    {
2978      throw wrapIOExceptionInDriverSQLException("getTablePrivileges", e);
2979    }
2980  }
2981
2982  /**
2983   * @see java.sql.DatabaseMetaData#getSchemas()
2984   */

2985  public synchronized ResultSet JavaDoc getSchemas() throws DriverSQLException
2986  {
2987    throwSQLExceptionIfClosed();
2988    String JavaDoc myName = "Connection.getSchemas()";
2989
2990    try
2991    {
2992      socketOutput.writeInt(Commands.DatabaseMetaDataGetSchemas);
2993      socketOutput.flush();
2994
2995      if (cjdbcUrl.isDebugEnabled())
2996        System.out.println(myName);
2997
2998      return receiveResultSet(myName);
2999    }
3000    catch (SerializableException e)
3001    {
3002      throw new DriverSQLException(e);
3003    }
3004    catch (IOException JavaDoc e)
3005    {
3006      throw wrapIOExceptionInDriverSQLException("getSchemas", e);
3007    }
3008  }
3009
3010  /**
3011   * @see DatabaseMetaData#getDatabaseProductName()
3012   */

3013  public synchronized String JavaDoc getDatabaseProductName() throws DriverSQLException
3014  {
3015    throwSQLExceptionIfClosed();
3016    try
3017    {
3018      socketOutput.writeInt(Commands.DatabaseMetaDataGetDatabaseProductName);
3019      socketOutput.flush();
3020
3021      if (cjdbcUrl.isDebugEnabled())
3022        System.out.println("Connection.getDatabaseProductName()");
3023
3024      return receiveString();
3025    }
3026    catch (SerializableException e)
3027    {
3028      throw new DriverSQLException(e);
3029    }
3030    catch (IOException JavaDoc e)
3031    {
3032      throw wrapIOExceptionInDriverSQLException("getDatabaseProductName", e);
3033    }
3034  }
3035
3036  /**
3037   * Fetch next fetchSize rows of data and update the given ResultSet.
3038   *
3039   * @see org.objectweb.cjdbc.controller.virtualdatabase.VirtualDatabaseWorkerThread#fetchNextResultSetRows()
3040   * @param cursorName name of the ResultSet cursor
3041   * @param fetchSize number of rows to fetch
3042   * @param drsToUpdate DriverResultSet to update
3043   * @throws DriverSQLException if an error occurs
3044   */

3045  public synchronized void fetchNextData(String JavaDoc cursorName, int fetchSize,
3046      DriverResultSet drsToUpdate) throws DriverSQLException
3047  {
3048    throwSQLExceptionIfClosed();
3049    try
3050    {
3051      socketOutput.writeInt(Commands.FetchNextResultSetRows);
3052      socketOutput.writeUTF(cursorName);
3053      socketOutput.writeInt(fetchSize);
3054      socketOutput.flush();
3055      if (cjdbcUrl.isDebugEnabled())
3056        System.out
3057            .println("Fetching next " + fetchSize + " from " + cursorName);
3058
3059      TypeTag tag = new TypeTag(socketInput);
3060
3061      if (TypeTag.EXCEPTION.equals(tag))
3062        throw new DriverSQLException(receiveException());
3063
3064      if (!TypeTag.NOT_EXCEPTION.equals(tag))
3065        throw new ProtocolException();
3066
3067      drsToUpdate.receiveRows(socketInput);
3068
3069    }
3070    catch (IOException JavaDoc e)
3071    {
3072      throw wrapIOExceptionInDriverSQLException("fetchNextData", e);
3073    }
3074  }
3075
3076  /**
3077   * Closes the remote ResultSet given its cursor name.
3078   *
3079   * @param cursorName cursor name of the ResultSet to close.
3080   * @throws SQLException if an error occurs
3081   */

3082  public synchronized void closeRemoteResultSet(String JavaDoc cursorName)
3083      throws SQLException JavaDoc
3084  {
3085    throwSQLExceptionIfClosed();
3086    try
3087    {
3088      socketOutput.writeInt(Commands.CloseRemoteResultSet);
3089      socketOutput.writeUTF(cursorName);
3090      socketOutput.flush();
3091      if (cjdbcUrl.isDebugEnabled())
3092        System.out.println("Closing remote ResultSet");
3093
3094      receiveBoolean();
3095    }
3096    catch (SerializableException se)
3097    {
3098      throw new DriverSQLException(se);
3099    }
3100    catch (IOException JavaDoc e)
3101    {
3102      throw wrapIOExceptionInDriverSQLException("closeRemoteResultSet", e);
3103    }
3104  }
3105
3106  /**
3107   * Returns the booleanFalse value.
3108   *
3109   * @return Returns the booleanFalse.
3110   */

3111  public String JavaDoc getPreparedStatementBooleanFalse()
3112  {
3113    return preparedStatementBooleanFalse;
3114  }
3115
3116  /**
3117   * Sets the booleanFalse value.
3118   *
3119   * @param booleanFalse The booleanFalse to set.
3120   */

3121  public void setPreparedStatementBooleanFalse(String JavaDoc booleanFalse)
3122  {
3123    this.preparedStatementBooleanFalse = booleanFalse;
3124  }
3125
3126  /**
3127   * Returns the booleanTrue value.
3128   *
3129   * @return Returns the booleanTrue.
3130   */

3131  public String JavaDoc getPreparedStatementBooleanTrue()
3132  {
3133    return preparedStatementBooleanTrue;
3134  }
3135
3136  /**
3137   * Sets the booleanTrue value.
3138   *
3139   * @param booleanTrue The booleanTrue to set.
3140   */

3141  public void setPreparedStatementBooleanTrue(String JavaDoc booleanTrue)
3142  {
3143    this.preparedStatementBooleanTrue = booleanTrue;
3144  }
3145
3146  /**
3147   * Returns the escapeBackslash value.
3148   *
3149   * @return Returns the escapeBackslash.
3150   */

3151  public boolean isEscapeBackslash()
3152  {
3153    return escapeBackslash;
3154  }
3155
3156  /**
3157   * Sets the escapeBackslash value.
3158   *
3159   * @param escapeBackslash The escapeBackslash to set.
3160   */

3161  public void setEscapeBackslash(boolean escapeBackslash)
3162  {
3163    this.escapeBackslash = escapeBackslash;
3164  }
3165
3166  /**
3167   * Returns the escapeSingleQuote value.
3168   *
3169   * @return Returns the escapeSingleQuote.
3170   */

3171  public boolean isEscapeSingleQuote()
3172  {
3173    return escapeSingleQuote;
3174  }
3175
3176  /**
3177   * Sets the escapeSingleQuote value.
3178   *
3179   * @param escapeSingleQuote The escapeSingleQuote to set.
3180   */

3181  public void setEscapeSingleQuote(boolean escapeSingleQuote)
3182  {
3183    this.escapeSingleQuote = escapeSingleQuote;
3184  }
3185
3186  /**
3187   * Sets the driverProcessed value
3188   *
3189   * @param processedByDriver true if the PreparedStatement are processed by the
3190   * C-JDBC driver.
3191   */

3192  void setDriverProcessed(boolean processedByDriver)
3193  {
3194    this.driverProcessed = processedByDriver;
3195  }
3196
3197  /**
3198   * @see Connection#isDriverProcessed()
3199   */

3200  boolean isDriverProcessed()
3201  {
3202    return driverProcessed;
3203  }
3204
3205  /**
3206   * Sets the escapeCharacter value
3207   *
3208   * @param escapeChar the escapeChar value to set
3209   */

3210  public void setEscapeChar(String JavaDoc escapeChar)
3211  {
3212    this.escapeChar = escapeChar;
3213  }
3214
3215  /**
3216   * @return Returns the escapeChar.
3217   */

3218  public String JavaDoc getEscapeChar()
3219  {
3220    return escapeChar;
3221  }
3222
3223  /**
3224   * Returns the connectionPooling value.
3225   *
3226   * @return Returns the connectionPooling.
3227   */

3228  public boolean isConnectionPooling()
3229  {
3230    return connectionPooling;
3231  }
3232
3233  /**
3234   * Sets the connectionPooling value.
3235   *
3236   * @param connectionPooling The connectionPooling to set.
3237   */

3238  public void setConnectionPooling(boolean connectionPooling)
3239  {
3240    this.connectionPooling = connectionPooling;
3241  }
3242
3243  /**
3244   * @see java.lang.Object#toString()
3245   */

3246  public String JavaDoc toString()
3247  {
3248    // couldn't we use println() or something here ?
3249
return "url:" + getUrl() + LINE_SEPARATOR + "user:" + getUserName()
3250        + LINE_SEPARATOR + "blobFilter:" + blobFilter + LINE_SEPARATOR
3251        + "connection pooling:" + connectionPooling + LINE_SEPARATOR
3252        + "driver processed:" + driverProcessed + LINE_SEPARATOR
3253        + "escape backslash:" + escapeBackslash + LINE_SEPARATOR
3254        + "escape char:" + escapeChar + LINE_SEPARATOR + "escape single quote:"
3255        + escapeSingleQuote + LINE_SEPARATOR + "preparedStatementBooleanTrue:"
3256        + preparedStatementBooleanTrue + LINE_SEPARATOR
3257        + "preparedStatementBooleanFalse" + preparedStatementBooleanFalse
3258        + LINE_SEPARATOR;
3259  }
3260
3261}
3262
Popular Tags