001: package org.apache.ojb.broker.platforms;
002:
003: /* Copyright 2003-2005 The Apache Software Foundation
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: import org.apache.ojb.broker.util.logging.Logger;
019: import org.apache.ojb.broker.util.logging.LoggerFactory;
020:
021: import java.io.*;
022: import java.sql.Connection;
023: import java.lang.reflect.InvocationTargetException;
024:
025: /**
026: * Handles the Oracle LOB problems for 9i.
027: *
028: * @author <a href="mailto:mattbaird@yahoo.com">Matthew Baird<a>
029: * @author <a href="mailto:erik@cj.com">Erik Forkalsrud</a>
030: * @author <a href="mailto:martin.kalen@curalia.se">Martin Kalén</a>
031: * @version CVS $Id: Oracle9iLobHandler.java,v 1.5.2.1 2005/12/21 22:26:40 tomdz Exp $
032: */
033: public class Oracle9iLobHandler {
034:
035: protected static Logger logger = LoggerFactory
036: .getLogger(Oracle9iLobHandler.class);
037:
038: private static ClobWrapper createTempCLOB(Connection connection,
039: ClobWrapper clob) {
040: if (clob == null) {
041: return null;
042: }
043:
044: ClobWrapper tempClob = null;
045: try {
046: // Create a temporary CLOB with duration session
047: tempClob = ClobWrapper.createTemporary(connection, true,
048: ClobWrapper.getDurationSessionValue());
049:
050: // Open the CLOB in readonly mode
051: clob.open(ClobWrapper.getModeReadOnlyValue());
052:
053: // Open the temporary CLOB in readwrite mode to enable writing
054: tempClob.open(ClobWrapper.getModeReadWriteValue());
055:
056: // No of bytes read each trip to database
057: int bytesread;
058:
059: // Get the input stream for reading from the CLOB
060: Reader clobReader = clob.getCharacterStream();
061:
062: // Get the output stream for writing into the CLOB
063: Writer tempClobWriter = tempClob.getCharacterOutputStream();
064:
065: // Create a buffer to read data
066: // getBufferSize() returns the optimal buffer size
067: char[] charbuffer = new char[clob.getBufferSize()];
068:
069: // Read from the CLOB and write into the temporary CLOB
070: while ((bytesread = clobReader.read(charbuffer)) != -1) {
071: tempClobWriter.write(charbuffer, 0, bytesread);
072: }
073:
074: // Flush and close the streams
075: tempClobWriter.flush();
076: tempClobWriter.close();
077: clobReader.close();
078:
079: // Close the CLOBs
080: clob.close();
081: tempClob.close();
082: } catch (Exception e) {
083: logger.error("Error during temporary CLOB write", e);
084: freeTempLOB(tempClob, null);
085: }
086: return tempClob;
087: }
088:
089: public static String convertCLOBtoString(Connection connection,
090: Object nativeclob) {
091: ClobWrapper temp = new ClobWrapper();
092: temp.setClob(nativeclob);
093: /**
094: * first, convert the clob to another clob. Thanks Oracle, you rule.
095: */
096: ClobWrapper clob = createTempCLOB(connection, temp);
097:
098: if (clob == null) {
099: return null;
100: }
101:
102: String retval = null;
103: // Buffer to hold the CLOB data
104: StringBuffer clobdata = new StringBuffer();
105: // No of bytes read each trip to database
106: int bytesread = 0;
107: try {
108: // Open the CLOB in readonly mode
109: clob.open(ClobWrapper.getModeReadOnlyValue());
110: // Open the stream to read data
111: Reader clobReader = clob.getCharacterStream();
112: // Buffer size is fixed using the getBufferSize() method which returns
113: // the optimal buffer size to read data from the LOB
114: char[] charbuffer = new char[clob.getBufferSize()];
115: // Keep reading from the CLOB and append it to the stringbuffer till
116: // there is no more to read
117: while ((bytesread = clobReader.read(charbuffer)) != -1) {
118: clobdata.append(charbuffer, 0, bytesread);
119: }
120: // Close the input stream
121: clobReader.close();
122: // Close the CLOB
123: clob.close();
124: retval = clobdata.toString();
125: clobdata = null;
126: } catch (Exception e) {
127: logger.error("Error during CLOB read", e);
128: freeTempLOB(clob, null);
129: }
130: return retval;
131: }
132:
133: public static Object createCLOBFromString(Connection conn,
134: String clobData) {
135: if (clobData == null) {
136: return null;
137: }
138: ClobWrapper clob = null;
139: try {
140: clob = ClobWrapper.createTemporary(conn, true, ClobWrapper
141: .getDurationSessionValue());
142: if (clob != null) {
143: // Open the temporary CLOB in readwrite mode to enable writing
144: clob.open(ClobWrapper.getModeReadWriteValue());
145:
146: // Clear the previous contents of the CLOB
147: clob.trim(0);
148:
149: // Get the output stream to write
150: Writer tempClobWriter = clob.getCharacterOutputStream();
151:
152: if (tempClobWriter != null) {
153: // Write the data into the temporary CLOB
154: tempClobWriter.write(clobData);
155:
156: // Flush and close the stream
157: tempClobWriter.flush();
158: tempClobWriter.close();
159: }
160:
161: // Close the temporary CLOB
162: clob.close();
163: }
164: } catch (InvocationTargetException ite) {
165: Throwable t = ite.getTargetException();
166: freeTempLOB(clob, null);
167: if (t instanceof java.lang.UnsatisfiedLinkError) {
168: logger
169: .error("Oracle JDBC-driver version does not match installed OCI-driver");
170: } else {
171: logger.error("Error during temporary CLOB write", t);
172: }
173: } catch (Exception e) {
174: logger.error("Error during temporary CLOB write", e);
175: freeTempLOB(clob, null);
176: }
177: return clob == null ? null : clob.getClob();
178: }
179:
180: private static BlobWrapper createTempBLOB(Connection connection,
181: BlobWrapper blob) {
182: if (blob == null) {
183: return null;
184: }
185:
186: BlobWrapper tempBlob = null;
187: try {
188: // Create a temporary BLOB with duration session
189: tempBlob = BlobWrapper.createTemporary(connection, true,
190: BlobWrapper.getDurationSessionValue());
191:
192: // Open the CLOB in readonly mode
193: blob.open(BlobWrapper.getModeReadOnlyValue());
194:
195: // Open the temporary CLOB in readwrite mode to enable writing
196: tempBlob.open(BlobWrapper.getModeReadWriteValue());
197:
198: // No of bytes read each trip to database
199: int bytesread;
200:
201: // Get the input stream for reading from the BLOB
202: InputStream blobInputStream = blob.getBinaryStream();
203:
204: // Get the output stream for writing into the BLOB
205: OutputStream tempBlobOutputStream = tempBlob
206: .getBinaryOutputStream();
207:
208: // Create a buffer to read data
209: // getBufferSize() returns the optimal buffer size
210: byte[] bytebuffer = new byte[blob.getBufferSize()];
211:
212: // Read from the BLOB and write into the temporary BLOB
213: while ((bytesread = blobInputStream.read(bytebuffer)) != -1) {
214: tempBlobOutputStream.write(bytebuffer, 0, bytesread);
215: }
216:
217: // Flush and close the streams
218: tempBlobOutputStream.flush();
219: tempBlobOutputStream.close();
220: blobInputStream.close();
221:
222: // Close the BLOBs
223: blob.close();
224: tempBlob.close();
225: } catch (Exception e) {
226: logger.error("Error during temporary BLOB write", e);
227: freeTempLOB(null, tempBlob);
228: }
229: return tempBlob;
230: }
231:
232: public static byte[] convertBLOBtoByteArray(Connection connection,
233: Object nativeblob) {
234: BlobWrapper temp = new BlobWrapper();
235: temp.setBlob(nativeblob);
236: /**
237: * first, convert the blob to another blob. Thanks Oracle, you rule.
238: */
239: BlobWrapper blob = createTempBLOB(connection, temp);
240: if (blob == null) {
241: return null;
242: }
243:
244: byte[] retval = null;
245: // Buffer to hold the BLOB data
246: ByteArrayOutputStream blobdata = new ByteArrayOutputStream();
247: // No of bytes read each trip to database
248: int bytesread = 0;
249: try {
250: // Open the BLOB in readonly mode
251: blob.open(BlobWrapper.getModeReadOnlyValue());
252: // Open the stream to read data
253: InputStream blobInputStream = blob.getBinaryStream();
254: // Buffer size is fixed using the getBufferSize() method which returns
255: // the optimal buffer size to read data from the LOB
256: byte[] bytebuffer = new byte[blob.getBufferSize()];
257: // Keep reading from the BLOB and append it to the bytebuffer till
258: // there is no more to read
259: while ((bytesread = blobInputStream.read(bytebuffer)) != -1) {
260: blobdata.write(bytebuffer, 0, bytesread);
261: }
262: // Close the input and output streams stream
263: blobInputStream.close();
264: blobdata.flush();
265: blobdata.close();
266:
267: // Close the BLOB
268: blob.close();
269: retval = blobdata.toByteArray();
270: blobdata = null;
271: } catch (Exception e) {
272: logger.error("Error during BLOB read", e);
273: freeTempLOB(null, blob);
274: }
275: return retval;
276: }
277:
278: public static Object createBLOBFromByteArray(Connection conn,
279: byte[] blobData) {
280: if (blobData == null) {
281: return null;
282: }
283:
284: BlobWrapper blob = null;
285: try {
286: blob = BlobWrapper.createTemporary(conn, true, BlobWrapper
287: .getDurationSessionValue());
288:
289: // Open the temporary BLOB in readwrite mode to enable writing
290: blob.open(BlobWrapper.getModeReadWriteValue());
291:
292: // Clear the previous contents of the BLOB
293: blob.trim(0);
294:
295: // Get the output stream to write
296: OutputStream tempBlobOutputStream = blob
297: .getBinaryOutputStream();
298:
299: // Write the data into the temporary BLOB
300: tempBlobOutputStream.write(blobData);
301:
302: // Flush and close the stream
303: tempBlobOutputStream.flush();
304: tempBlobOutputStream.close();
305:
306: // Close the temporary BLOB
307: blob.close();
308: } catch (InvocationTargetException ite) {
309: Throwable t = ite.getTargetException();
310: freeTempLOB(null, blob);
311: if (t instanceof java.lang.UnsatisfiedLinkError) {
312: logger
313: .error("Oracle JDBC-driver version does not match installed OCI-driver");
314: } else {
315: logger.error("Error during temporary BLOB write", t);
316: }
317: } catch (Exception e) {
318: logger.error("Error during temporary BLOB write", e);
319: freeTempLOB(null, blob);
320: }
321: return blob == null ? null : blob.getBlob();
322: }
323:
324: /**
325: * Frees the temporary LOBs when an exception is raised in the application
326: * or when the LOBs are no longer needed. If the LOBs are not freed, the
327: * space used by these LOBs are not reclaimed.
328: * @param clob CLOB-wrapper to free or null
329: * @param blob BLOB-wrapper to free or null
330: */
331: private static void freeTempLOB(ClobWrapper clob, BlobWrapper blob) {
332: try {
333: if (clob != null) {
334: // If the CLOB is open, close it
335: if (clob.isOpen()) {
336: clob.close();
337: }
338:
339: // Free the memory used by this CLOB
340: clob.freeTemporary();
341: }
342:
343: if (blob != null) {
344: // If the BLOB is open, close it
345: if (blob.isOpen()) {
346: blob.close();
347: }
348:
349: // Free the memory used by this BLOB
350: blob.freeTemporary();
351: }
352: } catch (Exception e) {
353: logger.error("Error during temporary LOB release", e);
354: }
355: }
356:
357: }
|