KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jcorporate > expresso > core > dataobjects > jdbc > LobField


1 /* ====================================================================
2  * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
3  *
4  * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in
15  * the documentation and/or other materials provided with the
16  * distribution.
17  *
18  * 3. The end-user documentation included with the redistribution,
19  * if any, must include the following acknowledgment:
20  * "This product includes software developed by Jcorporate Ltd.
21  * (http://www.jcorporate.com/)."
22  * Alternately, this acknowledgment may appear in the software itself,
23  * if and wherever such third-party acknowledgments normally appear.
24  *
25  * 4. "Jcorporate" and product names such as "Expresso" must
26  * not be used to endorse or promote products derived from this
27  * software without prior written permission. For written permission,
28  * please contact info@jcorporate.com.
29  *
30  * 5. Products derived from this software may not be called "Expresso",
31  * or other Jcorporate product names; nor may "Expresso" or other
32  * Jcorporate product names appear in their name, without prior
33  * written permission of Jcorporate Ltd.
34  *
35  * 6. No product derived from this software may compete in the same
36  * market space, i.e. framework, without prior written permission
37  * of Jcorporate Ltd. For written permission, please contact
38  * partners@jcorporate.com.
39  *
40  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
41  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
42  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
43  * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
44  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
46  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
47  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
48  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
49  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
50  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * ====================================================================
53  *
54  * This software consists of voluntary contributions made by many
55  * individuals on behalf of the Jcorporate Ltd. Contributions back
56  * to the project(s) are encouraged when you make modifications.
57  * Please send them to support@jcorporate.com. For more information
58  * on Jcorporate Ltd. and its products, please see
59  * <http://www.jcorporate.com/>.
60  *
61  * Portions of this software are based upon other open source
62  * products and are subject to their respective licenses.
63  */

64 package com.jcorporate.expresso.core.dataobjects.jdbc;
65
66 import com.jcorporate.expresso.core.dataobjects.DataException;
67 import com.jcorporate.expresso.core.dataobjects.DataFieldMetaData;
68 import com.jcorporate.expresso.core.db.DBConnection;
69 import com.jcorporate.expresso.core.db.DBConnectionPool;
70 import com.jcorporate.expresso.core.db.DBException;
71 import com.jcorporate.expresso.core.db.TypeMapper;
72 import com.jcorporate.expresso.kernel.util.FastStringBuffer;
73 import org.apache.log4j.Logger;
74
75 import java.io.IOException JavaDoc;
76 import java.io.InputStream JavaDoc;
77 import java.io.OutputStream JavaDoc;
78 import java.io.StringReader JavaDoc;
79 import java.io.Writer JavaDoc;
80 import java.lang.reflect.InvocationTargetException JavaDoc;
81 import java.lang.reflect.Method JavaDoc;
82 import java.sql.Blob JavaDoc;
83 import java.sql.Clob JavaDoc;
84 import java.sql.PreparedStatement JavaDoc;
85 import java.sql.ResultSet JavaDoc;
86 import java.sql.SQLException JavaDoc;
87
88 /**
89  * This class provides a low level BLOB capability while still keeping the
90  * programmer isolated from SQL syntax details.
91  * <p>The general usage is as follows:<br/>
92  * <code>
93  * &nbsp;MyDBObject myObj.setField("key1",1);<br/>
94  * &nbsp;LobField query = new LobField();<br/>
95  * &nbsp;query.setCriteria(myObj);<br/>
96  * &nbsp;java.io.InputStream inputStream = getBlobStream("blobFieldName");
97  * &nbsp; //Do whatever you want with the stream <br/>
98  * &nbsp; inputStream.flush();
99  * &nbsp; inputStream.close();
100  * &nbsp; query.close();
101  * </code>
102  * </p>
103  * <p>This class requires a JDBC 2 compliant driver for the BLOB/CLOB data types.
104  * Some drivers do not support these features, at which point you'll want
105  * to use the getBlobStream/getClobStream/getClobAsciiStream methods instead
106  * </p>
107  *
108  * @author Michael Rimov
109  * @since $DatabaseSchema $Date: 2004/11/18 02:03:27 $
110  */

111
112 public class LobField {
113
114     /**
115      * The dataobject to use to build the SQL search/update statements.
116      */

117     protected JDBCDataObject criteria = null;
118
119     /**
120      * The log4j Logger to use.
121      */

122     private Logger log = Logger.getLogger(LobField.class);
123
124     boolean alreadyInTransaction = false;
125
126     protected DBConnection myConnection = null;
127
128     /**
129      * Default constructor. Currently does nothing.
130      */

131     public LobField() {
132
133     }
134
135     /**
136      * Set the search criteria for the blob. All key fields must be present
137      * as this does a full retrieve() rather than a search on the data. Otherwise
138      * the object will throw an exception .
139      *
140      * @param newCriteria a filled out JDBCObject (DBObject derived classes work)
141      * with all keys present
142      * @throws DataException if all keys are not present.
143      */

144     public void setCriteria(JDBCDataObject newCriteria) throws DataException {
145         if (newCriteria == null) {
146             throw new IllegalArgumentException JavaDoc("Criteria cannot be null");
147         }
148
149         criteria = newCriteria;
150         if (newCriteria.getLocalConnection() != null) {
151             myConnection = newCriteria.getLocalConnection();
152         }
153     }
154
155
156     /**
157      * Protected method to get at the criteria object from any derived classes
158      *
159      * @return JDBCDataObject or null if no criteria has been set
160      */

161     protected JDBCDataObject getCriteria() {
162         return criteria;
163     }
164
165
166     /**
167      * Retrieves a <code>java.sql.Blob</code> object given the criteria object
168      * set previously.
169      *
170      * @param fieldName the name of the field to retrieve
171      * @return java.sql.Blob for the field
172      * @throws DataException if there is an error finding the object, an error
173      * retrieving the Blob from the system, or other database communication
174      * errors.
175      */

176     public Blob JavaDoc getBlob(String JavaDoc fieldName) throws DataException {
177         if (getCriteria() == null) {
178             throw new IllegalArgumentException JavaDoc("Criteria must be set before calling getBLob");
179         }
180
181         try {
182             if (myConnection == null) {
183                 myConnection = DBConnectionPool.getInstance(getCriteria()
184                         .getMappedDataContext()).getConnection("LOB Field Connection");
185             }
186         } catch (DBException ex) {
187             throw new DataException("Error getting Database" +
188                     " Connection for BLOB Retrieval", ex);
189         }
190
191         return getBLOB(getCriteria(), fieldName, myConnection);
192     }
193
194     /**
195      * Retrieves a <code>java.sql.Clob</code> object given the criteria object
196      * set previously.
197      *
198      * @param fieldName the name of the field to retrieve
199      * @return java.sql.Clob for the field
200      * @throws DataException if there is an error finding the object, an error
201      * retrieving the Clob from the system, or other database communication
202      * errors.
203      */

204     public Clob JavaDoc getClob(String JavaDoc fieldName) throws DataException {
205         if (getCriteria() == null) {
206             throw new IllegalArgumentException JavaDoc("Criteria must be set before calling getClob");
207         }
208
209         try {
210             if (myConnection == null) {
211                 myConnection = DBConnectionPool.getInstance(getCriteria()
212                         .getMappedDataContext()).getConnection("LOB Field Connection");
213             }
214         } catch (DBException ex) {
215             throw new DataException("Error getting Database" +
216                     " Connection for CLOB Retrieval", ex);
217         }
218
219         return getCLOB(getCriteria(), fieldName, myConnection);
220     }
221
222
223     /**
224      * Retrieve an input stream for a binary object stored in the database.
225      *
226      * @param fieldName the field name to retrieve.
227      * @return java.io.InputStream representing the BLOB object
228      * @throws DataException upon error
229      */

230     public InputStream JavaDoc getBlobStream(String JavaDoc fieldName) throws DataException {
231         if (getCriteria() == null) {
232             throw new IllegalArgumentException JavaDoc("Criteria must be set before calling getBLob");
233         }
234
235         try {
236             if (myConnection == null) {
237                 myConnection = DBConnectionPool.getInstance(getCriteria()
238                         .getMappedDataContext()).getConnection("LOB Field Connection");
239             }
240         } catch (DBException ex) {
241             throw new DataException("Error getting Database" +
242                     " Connection for BLOB Retrieval", ex);
243         }
244
245         try {
246             prepSelectResultSet(getCriteria(), fieldName, myConnection);
247             if (myConnection.next()) {
248                 return myConnection.getBinaryStream(1);
249             } else {
250                 return null;
251             }
252         } catch (DBException ex) {
253             throw new DataException("Error getting binary stream", ex);
254         }
255
256     }
257
258     /**
259      * Retrieve a java.io.Reader a.k.a Unicode stream for a CLOB field.
260      *
261      * @param fieldName the name of the field to retrieve.
262      * @return java.io.Reader for the Unicode CLOB stream stored in the database
263      * @throws DataException upon error retrieving the CLOB
264      */

265     public java.io.Reader JavaDoc getClobStream(String JavaDoc fieldName) throws DataException {
266         if (getCriteria() == null) {
267             throw new IllegalArgumentException JavaDoc("Criteria must be set before calling getBLob");
268         }
269
270         try {
271             if (myConnection == null) {
272                 myConnection = DBConnectionPool.getInstance(getCriteria()
273                         .getMappedDataContext()).getConnection("LOB Field Connection");
274             }
275         } catch (DBException ex) {
276             throw new DataException("Error getting Database" +
277                     " Connection for BLOB Retrieval", ex);
278         }
279
280         return this.getCLOBReader(getCriteria(), fieldName, myConnection);
281     }
282
283     /**
284      * CLOB convenience method. Reads the entire stream into a string. Note
285      * that if your field is large, this may take large amounts of memory
286      * to perform this operation. It is recommended to use getClobStream()
287      * for most purposes.
288      * <p>Note that this method is not supported by InterBase/InterClient 2 which
289      * does not support Unicode streams. Use getClobAsciiStream instead</p>
290      *
291      * @param fieldName the name of the field to retrieve
292      * @return java.lang.String containing the entire contents of the CLOB
293      * field.
294      * @throws DataException upon error.
295      */

296     public String JavaDoc getClobString(String JavaDoc fieldName) throws DataException {
297         java.io.Reader JavaDoc is = this.getClobStream(fieldName);
298         if (is == null) {
299             return null;
300         }
301
302         FastStringBuffer fsb = FastStringBuffer.getInstance();
303         try {
304
305             char[] buf = new char[1024]; // 1K buffer
306
int bytesRead;
307
308             while ((bytesRead = is.read(buf)) != -1) {
309                 fsb.append(buf, 0, bytesRead);
310             }
311
312             return fsb.toString();
313         } catch (java.io.IOException JavaDoc ex) {
314             throw new DataException("I/O Exception reading Character Stream");
315         } finally {
316             fsb.release();
317         }
318
319     }
320
321     /**
322      * Retrieve a java.io.InputStream a.k.a. ASCII stream for a CLOB field.
323      *
324      * @param fieldName the name of the field to retrieve.
325      * @return java.io.Reader for the ASCII CLOB stream stored in the database
326      * @throws DataException upon error retrieving the CLOB
327      */

328     public InputStream JavaDoc getClobAsciiStream(String JavaDoc fieldName) throws DataException {
329         try {
330             Clob JavaDoc theClob = getClob(fieldName);
331             return theClob.getAsciiStream();
332         } catch (SQLException JavaDoc ex) {
333             throw new DataException("Error getting clob ascii stream: " + fieldName, ex);
334         }
335     }
336
337
338     /**
339      * Saves an InputStream into the database given the criteria and the fieldname
340      * (Criteria should have been previously set).
341      *
342      * @param fieldName The name of the field to save the Stream to.
343      * @param data a java.io.InputStream object to save to the field. May be null
344      * if you want the field to be null.
345      * @param dataSize the length of the stream to save.
346      * @throws DataException upon database communications error.
347      * @throws IllegalArgumentException if fieldName is null.
348      */

349     public void saveBlob(String JavaDoc fieldName, InputStream JavaDoc data, int dataSize) throws DataException {
350         try {
351             if (myConnection == null) {
352                 myConnection = DBConnectionPool.getInstance(getCriteria()
353                         .getMappedDataContext()).getConnection("LOB Field Connection");
354
355                 if ("org.hsqldb.jdbcDriver".equals(myConnection.getDBDriver())) {
356                     //check the database size.
357
//Hypersonic has a maximum practical capability of 200K MAX
358
if (dataSize > 1024 * 200) {
359                         throw new DataException("HSQLDB can only store maxium of 200K files");
360                     }
361                 }
362             }
363         } catch (DBException ex) {
364             throw new DataException("Error getting Database" +
365                     " Connection for BLOB Retrieval", ex);
366         }
367
368         try {
369             alreadyInTransaction = !(myConnection.getAutoCommit());
370         } catch (DBException ex) {
371             throw new DataException("Error getting Database" +
372                     " Connection transaction parameter for BLOB Retrieval", ex);
373         }
374
375         // if running Oracle, use Oracle specific methods because of Oracle's
376
// incompatibility with standard jdbc LOB mothods
377
if ("oracle.jdbc.driver.OracleDriver".equals(myConnection.getDBDriver())) {
378             oracleSaveBlob(fieldName, data, dataSize);
379             return;
380         }
381
382
383         PreparedStatement JavaDoc preparedStatement = prepUpdate(getCriteria(), fieldName, myConnection);
384
385         try {
386             if (data == null) {
387                 DataFieldMetaData metaData = getCriteria().getFieldMetaData(fieldName);
388                 int typeCode = TypeMapper.getInstance(getCriteria().getMappedDataContext())
389                         .getJavaSQLType(metaData.getTypeString());
390                 preparedStatement.setNull(1, typeCode);
391             } else {
392                 preparedStatement.setBinaryStream(1, data, dataSize);
393             }
394         } catch (SQLException JavaDoc ex) {
395             throw new DataException("Unable to set CharacterStream to CLOB object.", ex);
396         } catch (DBException ex) {
397             throw new DataException("Unable to get Type Mapping information for Clob field", ex);
398         }
399
400         finalizeUpdate(myConnection);
401
402     }
403
404     /**
405      * Saves a <code>java.sql.Blob</code> to the record matching the criteria
406      * earlier set.
407      *
408      * @param fieldName the name of the field to save to
409      * @param data the <code>java.sql.Blob</code> based object to save to the
410      * database.
411      * @throws DataException upon database communication error
412      * @throws IllegalArgumentException if data is null
413      */

414     public void saveBlob(String JavaDoc fieldName, Blob JavaDoc data) throws DataException {
415         try {
416             if (myConnection == null) {
417                 myConnection = DBConnectionPool.getInstance(getCriteria()
418                         .getMappedDataContext()).getConnection("LOB Field Connection");
419             }
420         } catch (DBException ex) {
421             throw new DataException("Error getting Database" +
422                     " Connection for BLOB Retrieval", ex);
423         }
424
425         try {
426             alreadyInTransaction = !(myConnection.getAutoCommit());
427         } catch (DBException ex) {
428             throw new DataException("Error getting Database" +
429                     " Connection transaction parameter for BLOB Retrieval", ex);
430         }
431         PreparedStatement JavaDoc preparedStatement = prepUpdate(getCriteria(), fieldName, myConnection);
432
433         try {
434             if (data == null) {
435                 DataFieldMetaData metaData = getCriteria().getFieldMetaData(fieldName);
436                 int typeCode = TypeMapper.getInstance(getCriteria().getMappedDataContext())
437                         .getJavaSQLType(metaData.getTypeString());
438                 preparedStatement.setNull(1, typeCode);
439             } else {
440                 preparedStatement.setBlob(1, data);
441             }
442         } catch (SQLException JavaDoc ex) {
443             throw new DataException("Unable to set CharacterStream to CLOB object.", ex);
444         } catch (DBException ex) {
445             throw new DataException("Unable to get type mapping information", ex);
446         }
447
448         finalizeUpdate(myConnection);
449
450     }
451
452     /**
453      * Saves an InputStream into the database given the criteria and the fieldname
454      * (Criteria should have been previously set).
455      *
456      * @param fieldName The name of the field to save the Stream to.
457      * @param data a java.io.InputStream object to save to the field. May be null
458      * if you want the field to be null.
459      * @param length The size of the CLOB stream to save to the database
460      * @throws IllegalArgumentException if fieldName is null.
461      * @throws DataException upon database communications error.
462      */

463     public void saveClob(String JavaDoc fieldName, InputStream JavaDoc data, int length) throws DataException {
464
465         try {
466             if (myConnection == null) {
467                 myConnection = DBConnectionPool.getInstance(getCriteria()
468                         .getMappedDataContext()).getConnection("LOB Field Connection");
469             }
470         } catch (DBException ex) {
471             throw new DataException("Error getting Database" +
472                     " Connection for BLOB Retrieval", ex);
473         }
474
475         try {
476             alreadyInTransaction = !(myConnection.getAutoCommit());
477         } catch (DBException ex) {
478             throw new DataException("Error getting Database" +
479                     " Connection transaction parameter for BLOB Retrieval", ex);
480         }
481
482         // if running Oracle, use Oracle specific methods because of Oracle's incompatibility
483
// with standard jdbc LOB methods
484
if ("oracle.jdbc.driver.OracleDriver".equals(myConnection.getDBDriver())) {
485             oracleSaveClob(fieldName, data, length);
486             return;
487         }
488
489         PreparedStatement JavaDoc preparedStatement = prepUpdate(getCriteria(), fieldName, myConnection);
490
491         try {
492             if (data == null) {
493                 DataFieldMetaData metaData = getCriteria().getFieldMetaData(fieldName);
494                 int typeCode = TypeMapper.getInstance(getCriteria().getMappedDataContext())
495                         .getJavaSQLType(metaData.getTypeString());
496                 preparedStatement.setNull(1, typeCode);
497             } else {
498                 preparedStatement.setAsciiStream(1, data, length);
499             }
500         } catch (SQLException JavaDoc ex) {
501             throw new DataException("Unable to set CharacterStream to CLOB object.", ex);
502         } catch (DBException ex) {
503             throw new DataException("Unable to get type mapping information for CLOB object", ex);
504         }
505
506         finalizeUpdate(myConnection);
507
508     }
509
510     /**
511      * Saves an InputStream into the database given the criteria and the fieldname
512      * (Criteria should have been previously set).
513      *
514      * @param fieldName The name of the field to save the Stream to.
515      * @param data a java.io.Reader object to save to the field. May be null
516      * if you want the field to be null.
517      * @param length The size of the data stream to save to the database
518      * @throws DataException upon database communications error.
519      * @throws IllegalArgumentException if fieldName is null.
520      */

521     public void saveClob(String JavaDoc fieldName, java.io.Reader JavaDoc data, int length) throws DataException {
522
523         try {
524             if (myConnection == null) {
525                 myConnection = DBConnectionPool.getInstance(getCriteria()
526                         .getMappedDataContext()).getConnection("LOB Field Connection");
527             }
528         } catch (DBException ex) {
529             throw new DataException("Error getting Database" +
530                     " Connection for BLOB Retrieval", ex);
531         }
532
533         try {
534             alreadyInTransaction = !(myConnection.getAutoCommit());
535         } catch (DBException ex) {
536             throw new DataException("Error getting Database" +
537                     " Connection transaction parameter for BLOB Retrieval", ex);
538         }
539
540         if ("interbase.interclient.Driver".equals(myConnection.getDBDriver())) {
541             throw new DataException("InterBase Interclient 2 cannot support unicode data. " +
542                     " Must use saveClob(String, InputStream, length)" +
543                     "instead");
544         }
545
546         // if running Oracle, use Oracle specific methods because of Oracle's
547
// incompatibility with standard jdbc LOB mothods
548
if ("oracle.jdbc.driver.OracleDriver".equals(myConnection.getDBDriver())) {
549             if (data == null) {
550                 oracleSaveClob(fieldName, (StringReader JavaDoc) null, 0);
551             } else {
552                 oracleSaveClob(fieldName, data, length);
553             }
554             return;
555         }
556
557         PreparedStatement JavaDoc preparedStatement = prepUpdate(getCriteria(), fieldName, myConnection);
558
559         try {
560             if (data == null) {
561                 DataFieldMetaData metaData = getCriteria().getFieldMetaData(fieldName);
562                 int typeCode = TypeMapper.getInstance(getCriteria().getMappedDataContext())
563                         .getJavaSQLType(metaData.getTypeString());
564                 preparedStatement.setNull(1, typeCode);
565             } else {
566                 preparedStatement.setCharacterStream(1, data, length);
567             }
568         } catch (SQLException JavaDoc ex) {
569             throw new DataException("Unable to set CharacterStream to CLOB object.", ex);
570         } catch (DBException ex) {
571             throw new DataException("Unable to get type mapping information for CLOB field", ex);
572         }
573
574         finalizeUpdate(myConnection);
575     }
576
577     /**
578      * Saves a string to a CLOB field.
579      *
580      * @param fieldName the name of the field to save to.
581      * @param data the String value to save to the field.
582      * @throws DataException upon error
583      */

584     public void saveClob(String JavaDoc fieldName, String JavaDoc data) throws DataException {
585         try {
586             if (myConnection == null) {
587                 myConnection = DBConnectionPool.getInstance(getCriteria()
588                         .getMappedDataContext()).getConnection("LOB Field Connection");
589             }
590         } catch (DBException ex) {
591             throw new DataException("Error getting Database" +
592                     " Connection for BLOB Retrieval", ex);
593         }
594
595         try {
596             alreadyInTransaction = !(myConnection.getAutoCommit());
597         } catch (DBException ex) {
598             throw new DataException("Error getting Database" +
599                     " Connection transaction parameter for BLOB Retrieval", ex);
600         }
601
602         // if running Oracle, use Oracle specific methods because of Oracle's
603
// incompatibility with standard jdbc LOB mothods
604
if ("oracle.jdbc.driver.OracleDriver".equals(myConnection.getDBDriver())) {
605             if (data == null) {
606                 oracleSaveClob(fieldName, (StringReader JavaDoc) null, 0);
607             } else {
608                 oracleSaveClob(fieldName, new StringReader JavaDoc(data), data.length());
609             }
610             return;
611         }
612
613         PreparedStatement JavaDoc preparedStatement = prepUpdate(getCriteria(), fieldName, myConnection);
614
615         try {
616             if (data == null) {
617                 DataFieldMetaData metaData = getCriteria().getFieldMetaData(fieldName);
618                 int typeCode = TypeMapper.getInstance(getCriteria().getMappedDataContext())
619                         .getJavaSQLType(metaData.getTypeString());
620                 preparedStatement.setNull(1, typeCode);
621             } else {
622                 if ("interbase.interclient.Driver".equals(myConnection.getDBDriver())) {
623                     //
624
//Workaround, interclient 2 doesn't support setCharacterStream()
625
//
626
byte[] dataArray = data.getBytes();
627                     java.io.ByteArrayInputStream JavaDoc bis = new java.io.ByteArrayInputStream JavaDoc(dataArray);
628                     preparedStatement.setAsciiStream(1, bis, dataArray.length);
629                 } else {
630                     java.io.Reader JavaDoc r = new java.io.StringReader JavaDoc(data);
631                     preparedStatement.setCharacterStream(1, r, data.length());
632                 }
633             }
634         } catch (SQLException JavaDoc ex) {
635             throw new DataException("Unable to set CharacterStream to CLOB object.", ex);
636         } catch (DBException ex) {
637             throw new DataException("Unable to get type information for CLOB field", ex);
638         }
639
640         finalizeUpdate(myConnection);
641
642     }
643
644     /**
645      * Saves an InputStream into the database given the criteria and the fieldname
646      * (Criteria should have been previously set).
647      *
648      * @param fieldName The name of the field to save the Stream to.
649      * @param data a java.io.Reader object to save to the field. May be null
650      * if you want the field to be null.
651      * @throws DataException upon database communications error.
652      * @throws IllegalArgumentException if fieldName is null.
653      */

654     public void saveClob(String JavaDoc fieldName, Clob JavaDoc data) throws DataException {
655
656         try {
657             if (myConnection == null) {
658                 myConnection = DBConnectionPool.getInstance(getCriteria()
659                         .getMappedDataContext()).getConnection("LOB Field Connection");
660             }
661         } catch (DBException ex) {
662             throw new DataException("Error getting Database" +
663                     " Connection for BLOB Retrieval", ex);
664         }
665
666         try {
667             alreadyInTransaction = !(myConnection.getAutoCommit());
668         } catch (DBException ex) {
669             throw new DataException("Error getting Database" +
670                     " Connection transaction parameter for BLOB Retrieval", ex);
671         }
672
673         PreparedStatement JavaDoc preparedStatement = prepUpdate(getCriteria(), fieldName, myConnection);
674
675         try {
676             if (data == null) {
677                 DataFieldMetaData metaData = getCriteria().getFieldMetaData(fieldName);
678                 int typeCode = TypeMapper.getInstance(getCriteria().getMappedDataContext())
679                         .getJavaSQLType(metaData.getTypeString());
680                 preparedStatement.setNull(1, typeCode);
681             } else {
682                 preparedStatement.setClob(1, data);
683             }
684         } catch (SQLException JavaDoc ex) {
685             throw new DataException("Unable to set CharacterStream to CLOB object.", ex);
686         } catch (DBException ex) {
687             throw new DataException("Unable to get type mapping information for CLOB field", ex);
688         }
689
690         finalizeUpdate(myConnection);
691     }
692
693
694     /**
695      * Close the query resources held by the object. This should be wrapped
696      * in a try/finally block so that database connection resources are not
697      * left floating in limbo.
698      */

699     public void close() {
700         if (myConnection != null) {
701             if (log.isDebugEnabled()) {
702                 log.debug("Closing and releasing LOB connection");
703             }
704             try {
705                 if (!alreadyInTransaction && myConnection.supportsTransactions()) {
706                     myConnection.release();
707                 }
708             } catch (DBException ex) {
709 // throw new DataException("Error getting Database" +
710
// " Connection transaction parameter for BLOB Retrieval", ex);
711
}
712             myConnection = null;
713         }
714     }
715
716     /**
717      * Override of base object finalization to make sure that the database
718      * resources are closed if for some reason they haven't had this done
719      * to them already.
720      */

721     protected void finalize() throws java.lang.Throwable JavaDoc {
722         if (myConnection != null) {
723             log.warn("LobField was not closed before Garbage Collection!");
724             close();
725         }
726         super.finalize();
727     }
728
729
730     /**
731      * Retrieves the CLOB data for the specified DBObject and the specified
732      * fieldName
733      *
734      * @param baseObject The dbobject containing all the table information, and
735      * key fields set.
736      * @param fieldName The name of the field to retrieve as a LOB.
737      * @param theConnection a <code>DBConnection</code> object that has already
738      * been retrieved from the <code>DBConnectionPool</code>
739      * @return a java.sql.CLOB object.
740      * @throws DataException if there's an error executing the statement
741      */

742     private Clob JavaDoc getCLOB(JDBCDataObject baseObject,
743                          String JavaDoc fieldName,
744                          DBConnection theConnection) throws DataException {
745         prepSelectResultSet(baseObject, fieldName, theConnection);
746
747         try {
748             if (theConnection.next()) {
749                 return theConnection.getClob(fieldName);
750             }
751         } catch (DBException ex) {
752             throw new DataException("Error getting CLOB object from connection", ex);
753         }
754
755         return null;
756     }
757
758     /**
759      * Retrieves the CLOB data for the specified DBObject and the specified
760      * fieldName
761      *
762      * @param baseObject The dbobject containing all the table information, and
763      * key fields set.
764      * @param fieldName The name of the field to retrieve as a LOB.
765      * @param theConnection a <code>DBConnection</code> object that has already
766      * been retrieved from the <code>DBConnectionPool</code>
767      * @return a Reader object.
768      * @throws DataException if there's an error executing the statement
769      */

770     private java.io.Reader JavaDoc getCLOBReader(JDBCDataObject baseObject,
771                                          String JavaDoc fieldName,
772                                          DBConnection theConnection) throws DataException {
773         prepSelectResultSet(baseObject, fieldName, theConnection);
774         ResultSet JavaDoc rs = theConnection.getResultSet();
775         try {
776             if (rs.next()) {
777                 try {
778                     return rs.getCharacterStream(1);
779                 } catch (SQLException JavaDoc ex) {
780                     return new java.io.StringReader JavaDoc(rs.getString(1));
781                 }
782             }
783         } catch (java.sql.SQLException JavaDoc ex) {
784             throw new DataException("Error getting CLOB object from connection", ex);
785         }
786
787         return null;
788     }
789
790     /**
791      * Returns a single stream for a LOB object. This single LOB object is
792      * not wrapped by any javax.activation code and therefore is strictly up to
793      * the code creator on how to use the Input Stream.
794      *
795      * @param baseObject The dbobject containing all the table information, and
796      * key fields set.
797      * @param fieldName The name of the field to retrieve as a LOB.
798      * @param theConnection a <code>DBConnection</code> object that has already
799      * been retrieved from the <code>DBConnectionPool</code>
800      * @return an array of bytes that will contain the BLOB
801      * @throws DataException if there's an error executing the statement
802      */

803     private Blob JavaDoc getBLOB(JDBCDataObject baseObject,
804                          String JavaDoc fieldName,
805                          DBConnection theConnection) throws DataException {
806
807         try {
808             prepSelectResultSet(baseObject, fieldName, theConnection);
809             if (theConnection.next()) {
810                 return theConnection.getBlob(1);
811             } else {
812                 return null;
813             }
814         } catch (DBException ex) {
815             throw new DataException("Error getting Blob Field", ex);
816         }
817
818     }
819
820     /**
821      * Internal helper function that does the guts of the work
822      *
823      * @param baseObject The object that contains the metadata for this BLOB
824      * @param fieldName the name of the field that is the BLOB field
825      * @param theConnection an already allocated DBConnection object. <b>This
826      * function modifies the state of theConnection by allocating a prepared
827      * statement</b>
828      * @throws DataException upon error
829      * <p/>
830      * Modify by Yves Henri AMAIZO <amy_amaizo@compuserve.com>
831      * @since $DatabaseSchema $Date: 2004/11/18 02:03:27 $
832      */

833     protected void prepSelectResultSet(JDBCDataObject baseObject,
834                                        String JavaDoc fieldName,
835                                        DBConnection theConnection) throws DataException {
836         try {
837             FastStringBuffer prepStatement = FastStringBuffer.getInstance();
838             prepStatement.append("SELECT ");
839             prepStatement.append(fieldName);
840             prepStatement.append(" from ");
841             prepStatement.append(baseObject.getJDBCMetaData().getTargetSQLTable(baseObject.getDataContext()));
842             String JavaDoc whereClause = JDBCUtil.getInstance().buildWhereClause(baseObject, false);
843             prepStatement.append(whereClause);
844             String JavaDoc thePrepString = prepStatement.toString();
845             prepStatement.release();
846
847             if (log.isDebugEnabled()) {
848                 log.debug("Preparing prepared statement: " + thePrepString);
849             }
850
851             PreparedStatement JavaDoc prep = theConnection.createPreparedStatement(thePrepString);
852             if (prep == null) {
853                 throw new DataException("Unable to create prepared statement for CLOB retrieval." +
854                         " Check DBConnection log for details");
855             }
856             theConnection.execute();
857
858             if (log.isDebugEnabled()) {
859                 log.debug("Succesfully executed prepared statement");
860             }
861         } catch (DBException ex) {
862             throw new DataException("Error prepping SELECT ResultSet", ex);
863         }
864     }
865
866     /**
867      * Internal helper function to prepare a LOB update
868      *
869      * @param baseObject The object that contains the metadata for this BLOB
870      * @param fieldName the name of the field that is the BLOB field
871      * @param theConnection an already allocated DBConnection object
872      * @return a created PreparedStatement object
873      * @throws DataException Modify by Yves Henri AMAIZO <amy_amaizo@compuserve.com>
874      * @since $DatabaseSchema $Date: 2004/11/18 02:03:27 $
875      */

876     protected PreparedStatement JavaDoc prepUpdate(JDBCDataObject baseObject,
877                                            String JavaDoc fieldName,
878                                            DBConnection theConnection) throws DataException {
879         try {
880             String JavaDoc whereClause = JDBCUtil.getInstance().buildWhereClause(baseObject, false);
881
882             FastStringBuffer prepStatement = FastStringBuffer.getInstance();
883             String JavaDoc theSQL = null;
884             try {
885                 prepStatement.append("UPDATE ");
886                 prepStatement.append(baseObject.getJDBCMetaData().getTargetSQLTable(baseObject.getDataContext()));
887                 prepStatement.append(" SET ");
888                 prepStatement.append(fieldName);
889                 prepStatement.append(" = ? ");
890                 prepStatement.append(whereClause);
891                 theSQL = prepStatement.toString();
892             } finally {
893                 prepStatement.release();
894                 prepStatement = null;
895             }
896
897             return theConnection.createPreparedStatement(theSQL);
898         } catch (DBException ex) {
899             throw new DataException("Error prepping LOB update", ex);
900         }
901     }
902
903     protected void finalizeUpdate(DBConnection theConnection) throws DataException {
904
905         try {
906             boolean success = false;
907
908             //
909
//SAPDB and others REQUIRE that BLOB updates be done within a transaction. So
910
//If we aren't already within one, we enter one now. Then commit
911
//if a transaction wasn't already in process
912
//
913
if (!alreadyInTransaction && theConnection.supportsTransactions()) {
914                 if (log.isDebugEnabled()) {
915                     log.debug("Turning off auto-commit");
916                 }
917                 theConnection.setAutoCommit(false);
918             }
919
920             try {
921                 theConnection.executeUpdate(null);
922                 success = true;
923             } finally {
924                 if (success == false) {
925                     if (!alreadyInTransaction && theConnection.supportsTransactions()) {
926                         if (log.isDebugEnabled()) {
927                             log.debug("rolling back");
928                         }
929                         theConnection.rollback();
930                     }
931                 }
932                 if (!alreadyInTransaction && theConnection.supportsTransactions()) {
933                     if (log.isDebugEnabled()) {
934                         log.debug("Finishing commit and turning auto-commit back to true");
935                     }
936                     theConnection.commit();
937                     theConnection.setAutoCommit(true);
938                 }
939             }
940         } catch (DBException ex) {
941             throw new DataException("Error finalizing LOB update", ex);
942         }
943
944     }
945
946     /**
947      * Updates the underlying table with a BLOB object. Same as the byte[] method
948      * but uses InputStreams intead
949      *
950      * @param baseObject The object that contains the metadata for this BLOB
951      * @param fieldName the name of the field that is the BLOB field
952      * @param theData the data as an InputStream
953      * @param dataLength the total length to be read from the InputStream
954      * @param theConnection an already allocated DBConnection object
955      * @throws DBException upon error
956      */

957     private void setBLOB(JDBCDataObject baseObject,
958                          String JavaDoc fieldName,
959                          InputStream JavaDoc theData,
960                          int dataLength,
961                          DBConnection theConnection) throws DBException {
962         PreparedStatement JavaDoc preparedStatement = prepUpdate(baseObject, fieldName, theConnection);
963
964
965         try {
966
967             preparedStatement.setBinaryStream(1, theData, dataLength);
968         } catch (SQLException JavaDoc ex) {
969             throw new DBException("Error setting BLOB object", ex);
970         }
971
972
973         finalizeUpdate(theConnection);
974     }
975
976     /**
977      * Writes a LONG Character string to the database.
978      *
979      * @param baseObject The object that contains the metadata for this BLOB
980      * @param fieldName the name of the field that is the BLOB field
981      * @param theData the data in a <code>String</code>
982      * @param theConnection an already allocated DBConnection object Currently
983      * may <b>not</b> be null
984      * @throws DBException upon error
985      */

986     private void setCLOB(JDBCDataObject baseObject,
987                          String JavaDoc fieldName,
988                          String JavaDoc theData,
989                          DBConnection theConnection) throws DBException {
990
991         PreparedStatement JavaDoc preparedStatement = prepUpdate(baseObject, fieldName, theConnection);
992
993         try {
994             if ("interbase.interclient.Driver".equals(theConnection.getDBDriver())) {
995                 //
996
//Workaround, interclient 2 doesn't support setCharacterStream()
997
//
998
byte[] data = theData.getBytes();
999                 java.io.ByteArrayInputStream JavaDoc bis = new java.io.ByteArrayInputStream JavaDoc(data);
1000                preparedStatement.setAsciiStream(1, bis, data.length);
1001            } else {
1002                java.io.Reader JavaDoc r = new java.io.StringReader JavaDoc(theData);
1003                preparedStatement.setCharacterStream(1, r, theData.length());
1004            }
1005        } catch (SQLException JavaDoc ex) {
1006            throw new DBException("Unable to set CharacterStream to CLOB object.", ex);
1007        }
1008
1009        finalizeUpdate(theConnection);
1010    }
1011
1012
1013    /**
1014     * Saves an InputStream into the database given the criteria and the fieldname
1015     * (Criteria should have been previously set).
1016     * <p/>
1017     * Specific to Oracle. Oracle (as of 9.2) does not support standard jdbc LOB
1018     * functionality.
1019     *
1020     * @param fieldName The name of the field to save the Stream to.
1021     * @param data a java.io.InputStream object to save to the field. May be null
1022     * if you want the field to be null.
1023     * @param dataSize the length of the stream to save.
1024     * @throws DataException upon database communications error.
1025     * @throws IllegalArgumentException if fieldName is null.
1026     */

1027    private void oracleSaveBlob(String JavaDoc fieldName, InputStream JavaDoc data, int dataSize) throws DataException {
1028        try {
1029            if (myConnection == null) {
1030                myConnection = DBConnectionPool.getInstance(getCriteria()
1031                        .getMappedDataContext()).getConnection("LOB Field Connection");
1032            }
1033        } catch (DBException ex) {
1034            throw new DataException("Error getting Database" +
1035                    " Connection for BLOB Retrieval", ex);
1036        }
1037
1038        // update the BLOB with empty_blob() in case a LOB Locator doesn't yet
1039
// exist for the record
1040
oraclePrepUpdateEmptyLob(getCriteria(), fieldName, myConnection);
1041
1042        try {
1043            if (data != null) {
1044                oraclePrepSelectForUpdate(getCriteria(), fieldName, myConnection);
1045                if (myConnection.next()) {
1046                    // use reflection here so that Oracle classes are not needed for compilation. Performs the following:
1047
// - oracle.sql.BLOB blob = ((oracle.jdbc.driver.OracleResultSet)myConnection.getResultSet()).getBLOB(1);
1048
// - OutputStream oBlob = blob.getBinaryOutputStream();
1049
// - byte[] chunk = new byte[blob.getChunkSize()];
1050
Class JavaDoc oracleResultSetClass = Class.forName("oracle.jdbc.driver.OracleResultSet");
1051                    Class JavaDoc[] parameterTypes = new Class JavaDoc[]{int.class};
1052                    Object JavaDoc[] arguments = new Object JavaDoc[]{new Integer JavaDoc(1)};
1053                    Method JavaDoc getBlobMethod = oracleResultSetClass.getMethod("getBlob", parameterTypes);
1054                    Object JavaDoc blob = getBlobMethod.invoke((Object JavaDoc) myConnection.getResultSet(), arguments);
1055
1056                    parameterTypes = new Class JavaDoc[]{};
1057                    arguments = new Object JavaDoc[]{};
1058                    Class JavaDoc oracleBlobClass = Class.forName("oracle.sql.BLOB");
1059                    Method JavaDoc getBinaryOutputStreamMethod = oracleBlobClass.getMethod("getBinaryOutputStream",
1060                            parameterTypes);
1061                    OutputStream JavaDoc oBlob = (OutputStream JavaDoc) getBinaryOutputStreamMethod.invoke(blob, arguments);
1062
1063                    Method JavaDoc getChunkSizeMethod = oracleBlobClass.getMethod("getChunkSize", parameterTypes);
1064                    byte[] chunk = new byte[((Integer JavaDoc) getChunkSizeMethod.invoke(blob, arguments)).intValue()];
1065
1066
1067                    int i = -1;
1068                    while ((i = data.read(chunk)) != -1) {
1069                        oBlob.write(chunk, 0, i);
1070                    }
1071
1072                    oBlob.close();
1073                    data.close();
1074                    // release the row lock that the select for update created
1075
if (!alreadyInTransaction && myConnection.supportsTransactions()) {
1076                        myConnection.commit();
1077                    }
1078                } else {
1079                    throw new DataException("Error SELECTing record for update.");
1080                }
1081            }
1082        } catch (DBException ex) {
1083            throw new DataException("Error SELECTing record for update.", ex);
1084        } catch (NoSuchMethodException JavaDoc ex) {
1085            throw new DataException("Reflection error on oracle classes.", ex);
1086        } catch (IllegalAccessException JavaDoc ex) {
1087            throw new DataException("Reflection error on oracle classes.", ex);
1088        } catch (InvocationTargetException JavaDoc ex) {
1089            throw new DataException("Reflection error on oracle classes.", ex);
1090        } catch (ClassNotFoundException JavaDoc ex) {
1091            throw new DataException("Reflection error on oracle classes.", ex);
1092        } catch (IOException JavaDoc ex) {
1093            throw new DataException("Error reading from InputStream.", ex);
1094        }
1095    }
1096
1097    /**
1098     * Saves an InputStream into the database given the criteria and the fieldname
1099     * (Criteria should have been previously set).
1100     * <p/>
1101     * Specific to Oracle. Oracle (as of 9.2) does not support standard jdbc LOB
1102     * functionality.
1103     *
1104     * @param fieldName The name of the field to save the Stream to.
1105     * @param data a java.io.InputStream object to save to the field. May be null
1106     * if you want the field to be null.
1107     * @param length The size of the CLOB stream to save to the database
1108     * @throws IllegalArgumentException if fieldName is null.
1109     * @throws DataException upon database communications error.
1110     */

1111    private void oracleSaveClob(String JavaDoc fieldName, InputStream JavaDoc data, int length) throws DataException {
1112
1113        try {
1114            if (myConnection == null) {
1115                myConnection = DBConnectionPool.getInstance(getCriteria()
1116                        .getMappedDataContext()).getConnection("LOB Field Connection");
1117            }
1118        } catch (DBException ex) {
1119            throw new DataException("Error getting Database" +
1120                    " Connection for CLOB Retrieval", ex);
1121        }
1122
1123        if (data == null) {
1124            oraclePrepUpdateNullClob(getCriteria(), fieldName, myConnection);
1125            return;
1126        }
1127
1128        // update the CLOB with empty_clob() in case a LOB Locator doesn't yet
1129
// exist for the record
1130
oraclePrepUpdateEmptyLob(getCriteria(), fieldName, myConnection);
1131
1132        try {
1133            oraclePrepSelectForUpdate(getCriteria(), fieldName, myConnection);
1134            if (myConnection.next()) {
1135                // use reflection here so that Oracle classes are not needed for compilation. Performs the following:
1136
// - oracle.sql.BLOB blob = ((oracle.jdbc.driver.OracleResultSet)myConnection.getResultSet()).getCLOB(1);
1137
// - OutputStream oBlob = blob.getBinaryOutputStream();
1138
// - byte[] chunk = new byte[blob.getChunkSize()];
1139
Class JavaDoc oracleResultSetClass = Class.forName("oracle.jdbc.driver.OracleResultSet");
1140                Class JavaDoc[] parameterTypes = new Class JavaDoc[]{int.class};
1141                Object JavaDoc[] arguments = new Object JavaDoc[]{new Integer JavaDoc(1)};
1142                Method JavaDoc getClobMethod = oracleResultSetClass.getMethod("getClob", parameterTypes);
1143                Object JavaDoc clob = getClobMethod.invoke((Object JavaDoc) myConnection.getResultSet(), arguments);
1144
1145                parameterTypes = new Class JavaDoc[]{};
1146                arguments = new Object JavaDoc[]{};
1147                Class JavaDoc oracleClobClass = Class.forName("oracle.sql.CLOB");
1148                Method JavaDoc getAsciiOutputStreamMethod = oracleClobClass.getMethod("getAsciiOutputStreamMethod",
1149                        parameterTypes);
1150                OutputStream JavaDoc oClob = (OutputStream JavaDoc) getAsciiOutputStreamMethod.invoke(clob, arguments);
1151
1152                Method JavaDoc getChunkSizeMethod = oracleClobClass.getMethod("getChunkSize", parameterTypes);
1153                byte[] chunk = new byte[((Integer JavaDoc) getChunkSizeMethod.invoke(clob, arguments)).intValue()];
1154
1155
1156                int i = -1;
1157                while ((i = data.read(chunk)) != -1) {
1158                    oClob.write(chunk, 0, i);
1159                }
1160
1161                oClob.close();
1162                data.close();
1163                // release the row lock that the select for update created
1164
if (!alreadyInTransaction && myConnection.supportsTransactions()) {
1165                    myConnection.commit();
1166                }
1167            } else {
1168                throw new DataException("Error SELECTing record for update.");
1169            }
1170        } catch (DBException ex) {
1171            throw new DataException("Error SELECTing record for update.", ex);
1172        } catch (NoSuchMethodException JavaDoc ex) {
1173            throw new DataException("Reflection error on oracle classes.", ex);
1174        } catch (IllegalAccessException JavaDoc ex) {
1175            throw new DataException("Reflection error on oracle classes.", ex);
1176        } catch (InvocationTargetException JavaDoc ex) {
1177            throw new DataException("Reflection error on oracle classes.", ex);
1178        } catch (ClassNotFoundException JavaDoc ex) {
1179            throw new DataException("Reflection error on oracle classes.", ex);
1180        } catch (IOException JavaDoc ex) {
1181            throw new DataException("Error reading from InputStream.", ex);
1182        }
1183    }
1184
1185    /**
1186     * Saves a Reader into the database given the criteria and the fieldname
1187     * <p/>
1188     * Specific to Oracle. Oracle (as of 9.2) does not support standard jdbc LOB
1189     * functionality.
1190     * <p/>
1191     * (Criteria should have been previously set).
1192     *
1193     * @param fieldName The name of the field to save the Stream to.
1194     * @param data a java.io.Reader object to save to the field. May be null
1195     * if you want the field to be null.
1196     * @param length The size of the data stream to save to the database
1197     * @throws DataException upon database communications error.
1198     * @throws IllegalArgumentException if fieldName is null.
1199     */

1200    private void oracleSaveClob(String JavaDoc fieldName, java.io.Reader JavaDoc data, int length) throws DataException {
1201        try {
1202            if (myConnection == null) {
1203                myConnection = DBConnectionPool.getInstance(getCriteria()
1204                        .getMappedDataContext()).getConnection("LOB Field Connection");
1205            }
1206        } catch (DBException ex) {
1207            throw new DataException("Error getting Database" +
1208                    " Connection for CLOB Retrieval", ex);
1209        }
1210
1211        if (data == null) {
1212            oraclePrepUpdateNullClob(getCriteria(), fieldName, myConnection);
1213            return;
1214        }
1215
1216        // update the CLOB with empty_clob() in case a LOB Locator doesn't yet
1217
// exist for the record
1218
oraclePrepUpdateEmptyLob(getCriteria(), fieldName, myConnection);
1219
1220        try {
1221            oraclePrepSelectForUpdate(getCriteria(), fieldName, myConnection);
1222            if (myConnection.next()) {
1223                // use reflection here so that Oracle classes are not needed for compilation. Performs the following:
1224
// - oracle.sql.BLOB blob = ((oracle.jdbc.driver.OracleResultSet)myConnection.getResultSet()).getCLOB(1);
1225
// - Writer oBlob = getCharacterOutputStream();
1226
// - char[] chunk = new char[blob.getChunkSize()];
1227
Class JavaDoc oracleResultSetClass = Class.forName("oracle.jdbc.driver.OracleResultSet");
1228                Class JavaDoc[] parameterTypes = new Class JavaDoc[]{int.class};
1229                Object JavaDoc[] arguments = new Object JavaDoc[]{new Integer JavaDoc(1)};
1230                Method JavaDoc getClobMethod = oracleResultSetClass.getMethod("getClob", parameterTypes);
1231                Object JavaDoc clob = getClobMethod.invoke((Object JavaDoc) myConnection.getResultSet(), arguments);
1232
1233                parameterTypes = new Class JavaDoc[]{};
1234                arguments = new Object JavaDoc[]{};
1235                Class JavaDoc oracleClobClass = Class.forName("oracle.sql.CLOB");
1236                Method JavaDoc getCharacterOutputStream = oracleClobClass.getMethod("getCharacterOutputStream", parameterTypes);
1237                Writer JavaDoc oClob = (Writer JavaDoc) getCharacterOutputStream.invoke(clob, arguments);
1238
1239                Method JavaDoc getChunkSizeMethod = oracleClobClass.getMethod("getChunkSize", parameterTypes);
1240                char[] chunk = new char[((Integer JavaDoc) getChunkSizeMethod.invoke(clob, arguments)).intValue()];
1241
1242
1243                int i = -1;
1244                while ((i = data.read(chunk)) != -1) {
1245                    oClob.write(chunk, 0, i);
1246                }
1247
1248                oClob.close();
1249                data.close();
1250                // release the row lock that the select for update created
1251
if (!alreadyInTransaction && myConnection.supportsTransactions()) {
1252                    myConnection.commit();
1253                }
1254            } else {
1255                throw new DataException("Error SELECTing record for update.");
1256            }
1257        } catch (DBException ex) {
1258            throw new DataException("Error SELECTing record for update.", ex);
1259        } catch (NoSuchMethodException JavaDoc ex) {
1260            throw new DataException("Reflection error on oracle classes.", ex);
1261        } catch (IllegalAccessException JavaDoc ex) {
1262            throw new DataException("Reflection error on oracle classes.", ex);
1263        } catch (InvocationTargetException JavaDoc ex) {
1264            throw new DataException("Reflection error on oracle classes.", ex);
1265        } catch (ClassNotFoundException JavaDoc ex) {
1266            throw new DataException("Reflection error on oracle classes.", ex);
1267        } catch (IOException JavaDoc ex) {
1268            throw new DataException("Error reading from InputStream.", ex);
1269        }
1270    }
1271
1272    /**
1273     * Internal helper function to prepare a LOB update for Oracle.
1274     * Updates the record, setting the BLOB to to empty_blob() or CLOB to empty_clob() because inserts without
1275     * setting the LOB will result in a LOB Locator not being present, which will prevent
1276     * the LOB from being added to the record.
1277     *
1278     * @param baseObject The object that contains the metadata for this BLOB
1279     * @param fieldName the name of the field that is the BLOB field
1280     * @param theConnection an already allocated DBConnection object
1281     * @throws DataException Modify by Yves Henri AMAIZO <amy_amaizo@compuserve.com>
1282     * @since $DatabaseSchema $Date: 2004/11/18 02:03:27 $
1283     */

1284    private void oraclePrepUpdateEmptyLob(JDBCDataObject baseObject,
1285                                          String JavaDoc fieldName,
1286                                          DBConnection theConnection) throws DataException {
1287        try {
1288            String JavaDoc whereClause = JDBCUtil.getInstance().buildWhereClause(baseObject, false);
1289
1290            FastStringBuffer prepStatement = FastStringBuffer.getInstance();
1291            String JavaDoc theSQL = null;
1292            try {
1293                prepStatement.append("UPDATE ");
1294                prepStatement.append(baseObject.getJDBCMetaData().getTargetSQLTable(baseObject.getDataContext()));
1295                prepStatement.append(" SET ");
1296                prepStatement.append(fieldName);
1297                if (baseObject.getDataField(fieldName).getFieldMetaData().isCharacterLongObjectType()) {
1298                    prepStatement.append(" = empty_clob() ");
1299                } else {
1300                    prepStatement.append(" = empty_blob() ");
1301                }
1302                prepStatement.append(whereClause);
1303                theSQL = prepStatement.toString();
1304            } finally {
1305                prepStatement.release();
1306                prepStatement = null;
1307            }
1308
1309            theConnection.createPreparedStatement(theSQL);
1310            finalizeUpdate(theConnection);
1311        } catch (DBException ex) {
1312            throw new DataException("Error prepping LOB update", ex);
1313        }
1314    }
1315
1316    /**
1317     * Internal helper function to prepare a BLOB update for Oracle.
1318     * Updates the record, setting the BLOB to to empty_blob() because inserts without
1319     * setting the BLOB will result in a LOB Locator not being present, which will prevent
1320     * the BLOB from being added to the record.
1321     *
1322     * @param baseObject The object that contains the metadata for this BLOB
1323     * @param fieldName the name of the field that is the BLOB field
1324     * @param theConnection an already allocated DBConnection object
1325     * @throws DataException Modify by Yves Henri AMAIZO <amy_amaizo@compuserve.com>
1326     * @since $DatabaseSchema $Date: 2004/11/18 02:03:27 $
1327     */

1328    private void oraclePrepUpdateNullClob(JDBCDataObject baseObject,
1329                                          String JavaDoc fieldName,
1330                                          DBConnection theConnection) throws DataException {
1331        try {
1332            String JavaDoc whereClause = JDBCUtil.getInstance().buildWhereClause(baseObject, false);
1333
1334            FastStringBuffer prepStatement = FastStringBuffer.getInstance();
1335            String JavaDoc theSQL = null;
1336            try {
1337                prepStatement.append("UPDATE ");
1338                prepStatement.append(baseObject.getJDBCMetaData().getTargetSQLTable(baseObject.getDataContext()));
1339                prepStatement.append(" SET ");
1340                prepStatement.append(fieldName);
1341                prepStatement.append(" = null ");
1342                prepStatement.append(whereClause);
1343                theSQL = prepStatement.toString();
1344            } finally {
1345                prepStatement.release();
1346                prepStatement = null;
1347            }
1348
1349            theConnection.createPreparedStatement(theSQL);
1350            finalizeUpdate(theConnection);
1351        } catch (DBException ex) {
1352            throw new DataException("Error prepping CLOB update", ex);
1353        }
1354    }
1355
1356    /**
1357     * Internal helper function to prepare a BLOB update for Oracle.
1358     * Updates the record, setting the BLOB to to empty_blob() because inserts without
1359     * setting the BLOB will result in a LOB Locator not being present, which will prevent
1360     * the BLOB from being added to the record.
1361     *
1362     * @param baseObject The object that contains the metadata for this BLOB
1363     * @param fieldName the name of the field that is the BLOB field
1364     * @param theConnection an already allocated DBConnection object
1365     * @throws DataException Modify by Yves Henri AMAIZO <amy_amaizo@compuserve.com>
1366     * @since $DatabaseSchema $Date: 2004/11/18 02:03:27 $
1367     */

1368    protected void oraclePrepSelectForUpdate(JDBCDataObject baseObject,
1369                                             String JavaDoc fieldName,
1370                                             DBConnection theConnection) throws DataException {
1371        try {
1372            FastStringBuffer prepStatement = FastStringBuffer.getInstance();
1373            prepStatement.append("SELECT ");
1374            prepStatement.append(fieldName);
1375            prepStatement.append(" from ");
1376            prepStatement.append(baseObject.getJDBCMetaData().getTargetSQLTable(baseObject.getDataContext()));
1377            String JavaDoc whereClause = JDBCUtil.getInstance().buildWhereClause(baseObject, false);
1378            prepStatement.append(whereClause);
1379            prepStatement.append(" FOR UPDATE");
1380            String JavaDoc thePrepString = prepStatement.toString();
1381            prepStatement.release();
1382
1383            if (log.isDebugEnabled()) {
1384                log.debug("Preparing prepared statement: " + thePrepString);
1385            }
1386
1387            PreparedStatement JavaDoc prep = theConnection.createPreparedStatement(thePrepString);
1388            if (prep == null) {
1389                throw new DataException("Unable to create prepared statement for CLOB retrieval." +
1390                        " Check DBConnection log for details");
1391            }
1392            if (!alreadyInTransaction && theConnection.supportsTransactions()) {
1393                theConnection.setAutoCommit(false);
1394            }
1395            theConnection.execute();
1396
1397            if (log.isDebugEnabled()) {
1398                log.debug("Succesfully executed prepared statement");
1399            }
1400        } catch (DBException ex) {
1401            throw new DataException("Error prepping SELECT ResultSet", ex);
1402        }
1403    }
1404
1405}
1406
Popular Tags