001: /*
002:
003: Derby - Class org.apache.derby.client.am.Clob
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to You under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.client.am;
023:
024: import java.io.InputStream;
025: import java.io.IOException;
026: import java.io.Reader;
027: import java.sql.SQLException;
028: import org.apache.derby.shared.common.reference.SQLState;
029: import org.apache.derby.client.net.EncodedInputStream;
030:
031: public class Clob extends Lob implements java.sql.Clob {
032: //---------------------navigational members-----------------------------------
033:
034: //-----------------------------state------------------------------------------
035: protected String string_ = null;
036:
037: // Only used for input purposes. For output, each getXXXStream call
038: // must generate an independent stream.
039: protected java.io.InputStream asciiStream_ = null;
040: protected java.io.InputStream unicodeStream_ = null;
041: protected java.io.Reader characterStream_ = null;
042:
043: // used for input
044: // Therefore, we always convert a String to UTF-8 before we flow it for input
045: protected byte[] utf8String_;
046:
047: // the length of the clob returned by the LENGTH function.
048: protected long lengthInBytes_ = 0;
049:
050: private PreparedStatement internalLengthStmt_ = null;
051:
052: protected String encoding_ = "UNICODE";
053:
054: //This boolean variable indicates whether the Clob object has
055: //been invalidated by calling free() on it
056: private boolean isValid = true;
057:
058: //---------------------constructors/finalizer---------------------------------
059: public Clob(Agent agent, String string) {
060: this (agent);
061: string_ = string;
062: sqlLength_ = string_.length();
063: lengthObtained_ = true;
064: dataType_ |= STRING;
065: }
066:
067: // CTOR for output, when a btc isn't available; the encoding is
068: public Clob(Agent agent, byte[] unconvertedBytes,
069: String charsetName, int dataOffset) throws SqlException {
070: this (agent);
071: try {
072: // check for null encoding is needed because the net layer
073: // will no longer throw an exception if the server didn't specify
074: // a mixed or double byte ccsid (ccsid = 0). this check for null in the
075: // cursor is only required for types which can have mixed or double
076: // byte ccsids.
077: if (charsetName == null) {
078: throw new SqlException(
079: agent.logWriter_,
080: new ClientMessageId(
081: SQLState.CHARACTER_CONVERTER_NOT_AVAILABLE));
082: }
083:
084: string_ = new String(unconvertedBytes, dataOffset,
085: unconvertedBytes.length - dataOffset, charsetName);
086: sqlLength_ = string_.length();
087: lengthObtained_ = true;
088: dataType_ |= STRING;
089: } catch (java.io.UnsupportedEncodingException e) {
090: throw new SqlException(agent_.logWriter_,
091: new ClientMessageId(SQLState.UNSUPPORTED_ENCODING),
092: "byte[]", charsetName + " String", e);
093:
094: }
095: }
096:
097: // CTOR for ascii/unicode stream input
098: //"US-ASCII", "UTF-8", or "UnicodeBigUnmarked"
099: public Clob(Agent agent, java.io.InputStream inputStream,
100: String encoding, int length) throws SqlException {
101: this (agent);
102:
103: sqlLength_ = length;
104: lengthObtained_ = true;
105:
106: if (encoding.equals("US-ASCII")) {
107: asciiStream_ = inputStream;
108: dataType_ |= ASCII_STREAM;
109: } else if (encoding.equals("UTF-8")) { // "UTF-8"
110: unicodeStream_ = inputStream;
111: dataType_ |= UNICODE_STREAM;
112: } else if (encoding.equals("UnicodeBigUnmarked")) { // "UnicodeBigUnmarked"
113: try {
114: characterStream_ = new java.io.InputStreamReader(
115: inputStream, "UnicodeBigUnmarked");
116: } catch (java.io.UnsupportedEncodingException e) {
117: throw new SqlException(agent_.logWriter_,
118: new ClientMessageId(
119: SQLState.UNSUPPORTED_ENCODING),
120: "UnicodeBigUnmarked", "InputStreamReader", e);
121: }
122: dataType_ |= CHARACTER_STREAM;
123: sqlLength_ = length / 2;
124: }
125: }
126:
127: /**
128: * Create a <code>Clob</code> of unknown length with the specified
129: * encoding.
130: *
131: * This constructor was added to support the JDBC 4 length less overloads.
132: * Note that a <code>Clob</code> created with this constructor is made for
133: * input to the database only. Do not pass it out to the user!
134: *
135: * @param agent
136: * @param inputStream the data to insert
137: * @param encoding encoding to use for characters. Only "US-ASCII" is
138: * allowed.
139: */
140: public Clob(Agent agent, java.io.InputStream inputStream,
141: String encoding) throws SqlException {
142: this (agent);
143:
144: lengthObtained_ = false;
145:
146: if (encoding.equals("US-ASCII")) {
147: asciiStream_ = inputStream;
148: dataType_ |= ASCII_STREAM;
149: } else {
150: throw new SqlException(agent_.logWriter_,
151: new ClientMessageId(SQLState.UNSUPPORTED_ENCODING),
152: encoding + " InputStream", "String/Clob");
153: }
154: }
155:
156: // CTOR for character stream input
157: // THE ENCODING IS ASSUMED TO BE "UTF-16BE"
158: public Clob(Agent agent, java.io.Reader reader, int length) {
159: this (agent);
160: sqlLength_ = length;
161: lengthObtained_ = true;
162: characterStream_ = reader;
163: dataType_ |= CHARACTER_STREAM;
164: }
165:
166: /**
167: * Create a <code>Clob</code> of unknown length.
168: *
169: * This constructor was added to support the JDBC 4 length less overloads.
170: * Note that a <code>Clob</code> created with this constructor is made for
171: * input to the database only. Do not pass it out to the user!
172: *
173: * @param agent
174: * @param reader the data to insert
175: */
176: public Clob(Agent agent, Reader reader) {
177: this (agent);
178: lengthObtained_ = false;
179: // Wrap reader in stream to share code.
180: unicodeStream_ = EncodedInputStream.createUTF8Stream(reader);
181: // Override type to share logic with the other stream types.
182: dataType_ |= UNICODE_STREAM;
183: }
184:
185: private Clob(Agent agent) {
186: super (agent);
187: }
188:
189: protected void finalize() throws java.lang.Throwable {
190: super .finalize();
191: if (internalLengthStmt_ != null) {
192: internalLengthStmt_.closeX();
193: }
194: }
195:
196: // ---------------------------jdbc 2------------------------------------------
197: // Create another method lengthX for internal calls
198: public long length() throws SQLException {
199:
200: //call checkValidity to exit by throwing a SQLException if
201: //the Clob object has been freed by calling free() on it
202: checkValidity();
203:
204: try {
205: synchronized (agent_.connection_) {
206: if (agent_.loggingEnabled()) {
207: agent_.logWriter_.traceEntry(this , "length");
208: }
209:
210: if (lengthObtained_) {
211: return sqlLength_;
212: }
213: materializeStream();
214: lengthInBytes_ = super .sqlLength();
215:
216: if (agent_.loggingEnabled()) {
217: agent_.logWriter_.traceExit(this , "length",
218: sqlLength_);
219: }
220: return sqlLength_;
221: }
222: } catch (SqlException se) {
223: throw se.getSQLException();
224: }
225: }
226:
227: /**
228: * Returns a copy of the specified substring
229: * in the <code>CLOB</code> value
230: * designated by this <code>Clob</code> object.
231: * The substring begins at position
232: * <code>pos</code> and has up to <code>length</code> consecutive
233: * characters. The starting position must be between 1 and the length
234: * of the CLOB plus 1. This allows for zero-length CLOB values, from
235: * which only zero-length substrings can be returned.
236: * If a larger length is requested than there are characters available,
237: * characters to the end of the CLOB are returned.
238: * @param pos the first character of the substring to be extracted.
239: * The first character is at position 1.
240: * @param length the number of consecutive characters to be copied
241: * @return a <code>String</code> that is the specified substring in
242: * the <code>CLOB</code> value designated by this <code>Clob</code> object
243: * @exception SQLException if there is an error accessing the
244: * <code>CLOB</code>
245:
246: * NOTE: If the starting position is the length of the CLOB plus 1,
247: * zero characters are returned regardless of the length requested.
248: */
249: public String getSubString(long pos, int length)
250: throws SQLException {
251:
252: //call checkValidity to exit by throwing a SQLException if
253: //the Clob object has been freed by calling free() on it
254: checkValidity();
255:
256: try {
257: synchronized (agent_.connection_) {
258: String retVal = null;
259:
260: if (agent_.loggingEnabled()) {
261: agent_.logWriter_.traceEntry(this , "getSubString",
262: (int) pos, length);
263: }
264:
265: if (pos <= 0) {
266: throw new SqlException(agent_.logWriter_,
267: new ClientMessageId(
268: SQLState.BLOB_BAD_POSITION),
269: new Long(pos));
270: }
271:
272: if (length < 0) {
273: throw new SqlException(agent_.logWriter_,
274: new ClientMessageId(
275: SQLState.BLOB_NONPOSITIVE_LENGTH),
276: new Integer(length));
277: }
278:
279: if (pos > this .length() + 1) {
280: throw new SqlException(agent_.logWriter_,
281: new ClientMessageId(
282: SQLState.BLOB_POSITION_TOO_LARGE),
283: new Long(pos));
284: }
285: retVal = getSubStringX(pos, length);
286:
287: if (agent_.loggingEnabled()) {
288: agent_.logWriter_.traceExit(this , "getSubString",
289: retVal);
290: }
291: return retVal;
292: }
293: } catch (SqlException se) {
294: throw se.getSQLException();
295: }
296: }
297:
298: private String getSubStringX(long pos, int length)
299: throws SqlException {
300: try {
301: checkForClosedConnection();
302: // actual length is the lesser of the length requested
303: // and the number of characters available from pos to the end
304: long actualLength = Math.min(this .length() - pos + 1,
305: (long) length);
306: return string_.substring((int) pos - 1,
307: (int) (pos - 1 + actualLength));
308: } catch (SQLException se) {
309: throw new SqlException(se);
310: }
311: }
312:
313: public java.io.Reader getCharacterStream() throws SQLException {
314:
315: //call checkValidity to exit by throwing a SQLException if
316: //the Clob object has been freed by calling free() on it
317: checkValidity();
318:
319: try {
320: synchronized (agent_.connection_) {
321: if (agent_.loggingEnabled()) {
322: agent_.logWriter_.traceEntry(this ,
323: "getCharacterStream");
324: }
325:
326: java.io.Reader retVal = getCharacterStreamX();
327: if (agent_.loggingEnabled()) {
328: agent_.logWriter_.traceExit(this ,
329: "getCharacterStream", retVal);
330: }
331: return retVal;
332: }
333: } catch (SqlException se) {
334: throw se.getSQLException();
335: }
336: }
337:
338: private java.io.Reader getCharacterStreamX() throws SqlException {
339: checkForClosedConnection();
340:
341: if (isCharacterStream()) // this Lob is used for input
342: {
343: return characterStream_;
344: }
345:
346: return new java.io.StringReader(string_);
347: }
348:
349: public java.io.InputStream getAsciiStream() throws SQLException {
350:
351: //call checkValidity to exit by throwing a SQLException if
352: //the Clob object has been freed by calling free() on it
353: checkValidity();
354:
355: try {
356: synchronized (agent_.connection_) {
357: if (agent_.loggingEnabled()) {
358: agent_.logWriter_
359: .traceEntry(this , "getAsciiStream");
360: }
361:
362: java.io.InputStream retVal = getAsciiStreamX();
363: if (agent_.loggingEnabled()) {
364: agent_.logWriter_.traceExit(this , "getAsciiStream",
365: retVal);
366: }
367: return retVal;
368: }
369: } catch (SqlException se) {
370: throw se.getSQLException();
371: }
372: }
373:
374: private java.io.InputStream getAsciiStreamX() throws SqlException {
375: checkForClosedConnection();
376:
377: if (isAsciiStream()) // this Lob is used for input
378: {
379: return asciiStream_;
380: }
381:
382: return new AsciiStream(string_, new java.io.StringReader(
383: string_));
384: }
385:
386: public long position(String searchstr, long start)
387: throws SQLException {
388:
389: //call checkValidity to exit by throwing a SQLException if
390: //the Clob object has been freed by calling free() on it
391: checkValidity();
392:
393: try {
394: synchronized (agent_.connection_) {
395: if (agent_.loggingEnabled()) {
396: agent_.logWriter_.traceEntry(this ,
397: "position(String, long)", searchstr, start);
398: }
399: if (searchstr == null) {
400: throw new SqlException(
401: agent_.logWriter_,
402: new ClientMessageId(
403: SQLState.BLOB_NULL_PATTERN_OR_SEARCH_STR));
404: }
405: if (start < 1) {
406: throw new SqlException(agent_.logWriter_,
407: new ClientMessageId(
408: SQLState.BLOB_BAD_POSITION),
409: new Long(start));
410: }
411:
412: long pos = positionX(searchstr, start);
413: if (agent_.loggingEnabled()) {
414: agent_.logWriter_.traceExit(this ,
415: "position(String, long)", pos);
416: }
417: return pos;
418: }
419: } catch (SqlException se) {
420: throw se.getSQLException();
421: }
422: }
423:
424: private long positionX(String searchstr, long start)
425: throws SqlException {
426: checkForClosedConnection();
427:
428: if (start <= 0) {
429: throw new SqlException(
430: agent_.logWriter_,
431: new ClientMessageId(SQLState.INVALID_API_PARAMETER),
432: new Long(start), "start", "Clob.position()");
433: }
434:
435: int index = string_.indexOf(searchstr, (int) start - 1);
436: if (index != -1) {
437: index++; // api index starts at 1
438: }
439: return (long) index;
440: }
441:
442: public long position(java.sql.Clob searchstr, long start)
443: throws SQLException {
444:
445: //call checkValidity to exit by throwing a SQLException if
446: //the Clob object has been freed by calling free() on it
447: checkValidity();
448:
449: try {
450: synchronized (agent_.connection_) {
451: if (agent_.loggingEnabled()) {
452: agent_.logWriter_.traceEntry(this ,
453: "position(Clob, long)", searchstr, start);
454: }
455: if (start < 1) {
456: throw new SqlException(agent_.logWriter_,
457: new ClientMessageId(
458: SQLState.BLOB_BAD_POSITION),
459: new Long(start));
460: }
461:
462: if (searchstr == null) {
463: throw new SqlException(
464: agent_.logWriter_,
465: new ClientMessageId(
466: SQLState.BLOB_NULL_PATTERN_OR_SEARCH_STR));
467: }
468: long pos = positionX(searchstr, start);
469: if (agent_.loggingEnabled()) {
470: agent_.logWriter_.traceExit(this ,
471: "position(Clob, long)", pos);
472: }
473: return pos;
474: }
475: } catch (SqlException se) {
476: throw se.getSQLException();
477: }
478: }
479:
480: private long positionX(java.sql.Clob searchstr, long start)
481: throws SqlException {
482: checkForClosedConnection();
483:
484: if (start <= 0) {
485: throw new SqlException(
486: agent_.logWriter_,
487: new ClientMessageId(SQLState.INVALID_API_PARAMETER),
488: new Long(start), "start", "Clob.position()");
489: }
490:
491: // if the searchstr is longer than the source, no match
492: int index;
493: try {
494: if (searchstr.length() > length()) {
495: return -1;
496: }
497:
498: index = string_.indexOf(searchstr.getSubString(1L,
499: (int) searchstr.length()), (int) start - 1);
500: } catch (java.sql.SQLException e) {
501: throw new SqlException(e);
502: }
503: if (index != -1) {
504: index++; // api index starts at 1
505: }
506: return (long) index;
507: }
508:
509: //---------------------------- jdbc 3.0 -----------------------------------
510:
511: public int setString(long pos, String str) throws SQLException {
512:
513: //call checkValidity to exit by throwing a SQLException if
514: //the Clob object has been freed by calling free() on it
515: checkValidity();
516:
517: try {
518: synchronized (agent_.connection_) {
519: if (agent_.loggingEnabled()) {
520: agent_.logWriter_.traceEntry(this , "setString",
521: (int) pos, str);
522: }
523: int length = setStringX(pos, str, 0, str.length());
524: if (agent_.loggingEnabled()) {
525: agent_.logWriter_.traceExit(this , "setString",
526: length);
527: }
528: return length;
529: }
530: } catch (SqlException se) {
531: throw se.getSQLException();
532: }
533: }
534:
535: public int setString(long pos, String str, int offset, int len)
536: throws SQLException {
537:
538: //call checkValidity to exit by throwing a SQLException if
539: //the Clob object has been freed by calling free() on it
540: checkValidity();
541:
542: try {
543: synchronized (agent_.connection_) {
544: if (agent_.loggingEnabled()) {
545: agent_.logWriter_.traceEntry(this , "setString",
546: (int) pos, str, offset, len);
547: }
548: int length = setStringX(pos, str, offset, len);
549: if (agent_.loggingEnabled()) {
550: agent_.logWriter_.traceExit(this , "setString",
551: length);
552: }
553: return length;
554: }
555: } catch (SqlException se) {
556: throw se.getSQLException();
557: }
558: }
559:
560: public int setStringX(long pos, String str, int offset, int len)
561: throws SqlException {
562: if ((int) pos <= 0) {
563: throw new SqlException(agent_.logWriter_,
564: new ClientMessageId(SQLState.BLOB_BAD_POSITION),
565: new Long(pos));
566: }
567: if (pos - 1 > sqlLength_) {
568: throw new SqlException(agent_.logWriter_,
569: new ClientMessageId(
570: SQLState.BLOB_POSITION_TOO_LARGE),
571: new Long(pos));
572: }
573: if ((offset < 0) || offset > str.length()) {
574: throw new SqlException(agent_.logWriter_,
575: new ClientMessageId(SQLState.BLOB_INVALID_OFFSET),
576: new Integer(offset));
577: }
578:
579: if (len < 0) {
580: throw new SqlException(agent_.logWriter_,
581: new ClientMessageId(
582: SQLState.BLOB_NONPOSITIVE_LENGTH),
583: new Integer(len));
584: }
585:
586: if (len == 0) {
587: return 0;
588: }
589:
590: int length = 0;
591: length = Math.min((str.length() - offset), len);
592: String newString = string_.substring(0, (int) pos - 1);
593: string_ = newString.concat(str.substring(offset, offset
594: + length));
595: asciiStream_ = new java.io.StringBufferInputStream(string_);
596: unicodeStream_ = new java.io.StringBufferInputStream(string_);
597: characterStream_ = new java.io.StringReader(string_);
598: sqlLength_ = string_.length();
599: return length;
600: }
601:
602: public java.io.OutputStream setAsciiStream(long pos)
603: throws SQLException {
604:
605: //call checkValidity to exit by throwing a SQLException if
606: //the Clob object has been freed by calling free() on it
607: checkValidity();
608:
609: try {
610: synchronized (agent_.connection_) {
611: if (agent_.loggingEnabled()) {
612: agent_.logWriter_.traceEntry(this ,
613: "setAsciiStream", (int) pos);
614: }
615: ClobOutputStream outStream = new ClobOutputStream(this ,
616: pos);
617:
618: if (agent_.loggingEnabled()) {
619: agent_.logWriter_.traceExit(this , "setAsciiStream",
620: outStream);
621: }
622: return outStream;
623: }
624: } catch (SqlException se) {
625: throw se.getSQLException();
626: }
627: }
628:
629: public java.io.Writer setCharacterStream(long pos)
630: throws SQLException {
631:
632: //call checkValidity to exit by throwing a SQLException if
633: //the Clob object has been freed by calling free() on it
634: checkValidity();
635:
636: try {
637: synchronized (agent_.connection_) {
638: if (agent_.loggingEnabled()) {
639: agent_.logWriter_.traceEntry(this ,
640: "setCharacterStream", (int) pos);
641: }
642: ClobWriter writer = new ClobWriter(this , pos);
643:
644: if (agent_.loggingEnabled()) {
645: agent_.logWriter_.traceExit(this ,
646: "setCharacterStream", writer);
647: }
648: return writer;
649: }
650: } catch (SqlException se) {
651: throw se.getSQLException();
652: }
653: }
654:
655: public void truncate(long len) throws SQLException {
656:
657: //call checkValidity to exit by throwing a SQLException if
658: //the Clob object has been freed by calling free() on it
659: checkValidity();
660:
661: try {
662: synchronized (agent_.connection_) {
663: if (agent_.loggingEnabled()) {
664: agent_.logWriter_.traceEntry(this , " truncate",
665: (int) len);
666: }
667: if (len < 0) {
668: throw new SqlException(agent_.logWriter_,
669: new ClientMessageId(
670: SQLState.BLOB_NONPOSITIVE_LENGTH),
671: new Long(len));
672: }
673:
674: if (len > this .length()) {
675: throw new SqlException(agent_.logWriter_,
676: new ClientMessageId(
677: SQLState.BLOB_LENGTH_TOO_LONG),
678: new Long(len));
679: }
680:
681: if (len == this .length()) {
682: return;
683: }
684: String newstr = string_.substring(0, (int) len);
685: string_ = newstr;
686: asciiStream_ = new java.io.StringBufferInputStream(
687: string_);
688: unicodeStream_ = new java.io.StringBufferInputStream(
689: string_);
690: characterStream_ = new java.io.StringReader(string_);
691: sqlLength_ = string_.length();
692: }
693: } catch (SqlException se) {
694: throw se.getSQLException();
695: }
696: }
697:
698: //---------------------------- jdbc 4.0 -------------------------------------
699: /**
700: * This method frees the <code>Clob</code> object and releases the resources the resources
701: * that it holds. The object is invalid once the <code>free</code> method
702: * is called. If <code>free</code> is called multiple times, the
703: * subsequent calls to <code>free</code> are treated as a no-op.
704: *
705: * @throws SQLException if an error occurs releasing
706: * the Clob's resources
707: */
708: public void free() throws SQLException {
709:
710: //calling free() on a already freed object is treated as a no-op
711: if (!isValid)
712: return;
713:
714: //now that free has been called the Blob object is no longer
715: //valid
716: isValid = false;
717:
718: if (isString()) {
719: string_ = null;
720: utf8String_ = null;
721: }
722: if (isAsciiStream()) {
723: try {
724: asciiStream_.close();
725: } catch (IOException ioe) {
726: throw new SqlException(null, new ClientMessageId(
727: SQLState.IO_ERROR_UPON_LOB_FREE))
728: .getSQLException();
729: }
730: }
731: if (isUnicodeStream()) {
732: try {
733: unicodeStream_.close();
734: } catch (IOException ioe) {
735: throw new SqlException(null, new ClientMessageId(
736: SQLState.IO_ERROR_UPON_LOB_FREE))
737: .getSQLException();
738: }
739: }
740: if (isCharacterStream()) {
741: try {
742: characterStream_.close();
743: } catch (IOException ioe) {
744: throw new SqlException(null, new ClientMessageId(
745: SQLState.IO_ERROR_UPON_LOB_FREE))
746: .getSQLException();
747: }
748: }
749:
750: lengthInBytes_ = 0;
751:
752: if (internalLengthStmt_ != null) {
753: try {
754: internalLengthStmt_.closeX();
755: } catch (SqlException sqle) {
756: throw sqle.getSQLException();
757: }
758: }
759: }
760:
761: public Reader getCharacterStream(long pos, long length)
762: throws SQLException {
763: throw SQLExceptionFactory
764: .notImplemented("getCharacterStream(long,long");
765: }
766:
767: //----------------------------helper methods----------------------------------
768:
769: public boolean isString() {
770: return ((dataType_ & STRING) == STRING);
771: }
772:
773: public boolean isAsciiStream() {
774: return ((dataType_ & ASCII_STREAM) == ASCII_STREAM);
775: }
776:
777: public boolean isCharacterStream() {
778: return ((dataType_ & CHARACTER_STREAM) == CHARACTER_STREAM);
779: }
780:
781: public boolean isUnicodeStream() {
782: return ((dataType_ & UNICODE_STREAM) == UNICODE_STREAM);
783: }
784:
785: public java.io.InputStream getUnicodeStream() {
786: return unicodeStream_;
787: }
788:
789: public String getString() {
790: return string_;
791: }
792:
793: public byte[] getUtf8String() {
794: return utf8String_;
795: }
796:
797: // Return the length of the equivalent UTF-8 string
798: // precondition: string_ is not null and dataType_ includes STRING
799: public int getUTF8Length() throws SqlException {
800: if (utf8String_ != null) {
801: return utf8String_.length;
802: }
803:
804: try {
805: utf8String_ = string_.getBytes("UTF-8");
806: return utf8String_.length;
807: } catch (java.io.UnsupportedEncodingException e) {
808: throw new SqlException(agent_.logWriter_,
809: new ClientMessageId(SQLState.UNSUPPORTED_ENCODING),
810: "String", "UTF8 byte[]", e);
811: }
812: }
813:
814: // auxiliary method for position (Clob, long)
815: protected Clob createClobWrapper(java.sql.Clob clob)
816: throws SqlException {
817: long length;
818: java.io.Reader rdr;
819:
820: try {
821: length = clob.length();
822: } catch (java.sql.SQLException e) {
823: throw new SqlException(e);
824: }
825:
826: if (length > Integer.MAX_VALUE) {
827: throw new SqlException(agent_.logWriter_,
828: new ClientMessageId(
829: SQLState.BLOB_TOO_LARGE_FOR_CLIENT),
830: new Long(length), new Integer(Integer.MAX_VALUE));
831: }
832:
833: try {
834: rdr = clob.getCharacterStream();
835: } catch (java.sql.SQLException e) {
836: throw SqlException.javaException(agent_.logWriter_, e);
837: }
838:
839: return new Clob(this .agent_, rdr, (int) length);
840: }
841:
842: public void convertFromAsciiToCharacterStream() throws SqlException {
843: try {
844: characterStream_ = new java.io.InputStreamReader(
845: asciiStream_, "US-ASCII");
846: dataType_ = CHARACTER_STREAM;
847: } catch (java.io.UnsupportedEncodingException e) {
848: throw new SqlException(agent_.logWriter_,
849: new ClientMessageId(SQLState.UNSUPPORTED_ENCODING),
850: "US-ASCII", "CharacterStream", e);
851: }
852: }
853:
854: // this method is primarily for mixed clob length calculations.
855: // it was introduced to prevent recursion in the actual char length calculation
856: public long getByteLength() throws SQLException {
857: if (lengthObtained_ == true) {
858: return lengthInBytes_;
859: }
860:
861: length();
862: return lengthInBytes_;
863: }
864:
865: /*
866: * Checks is isValid is true. If it is not true throws
867: * a SQLException stating that a method has been called on
868: * an invalid LOB object
869: *
870: * throws SQLException if isvalid is not true.
871: */
872: private void checkValidity() throws SQLException {
873: if (!isValid)
874: throw new SqlException(null, new ClientMessageId(
875: SQLState.LOB_OBJECT_INVALID)).getSQLException();
876: }
877:
878: /**
879: * Materialize the stream used for input to the database.
880: */
881: private void materializeStream() throws SqlException {
882: unicodeStream_ = super .materializeStream(
883: isAsciiStream() ? asciiStream_ : unicodeStream_,
884: "java.sql.Clob");
885: dataType_ = UNICODE_STREAM;
886: }
887: }
|