001: /*
002: * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
003: * (http://h2database.com/html/license.html).
004: * Initial Developer: H2 Group
005: */
006: package org.h2.jdbc;
007:
008: import java.io.ByteArrayOutputStream;
009: import java.io.InputStream;
010: import java.io.OutputStream;
011: import java.sql.Blob;
012: import java.sql.SQLException;
013:
014: import org.h2.constant.ErrorCode;
015: import org.h2.engine.Constants;
016: import org.h2.engine.SessionInterface;
017: import org.h2.message.Message;
018: import org.h2.message.TraceObject;
019: import org.h2.util.IOUtils;
020: import org.h2.value.Value;
021:
022: /**
023: * Represents a BLOB value.
024: */
025: public class JdbcBlob extends TraceObject implements Blob {
026:
027: private Value value;
028: private JdbcConnection conn;
029:
030: /**
031: * INTERNAL
032: */
033: public JdbcBlob(SessionInterface session, JdbcConnection conn,
034: Value value, int id) {
035: setTrace(session.getTrace(), TraceObject.BLOB, id);
036: this .conn = conn;
037: this .value = value;
038: }
039:
040: /**
041: * Returns the length.
042: *
043: * @return the length
044: */
045: public long length() throws SQLException {
046: try {
047: debugCodeCall("length");
048: checkClosed();
049: if (value.getType() == Value.BLOB) {
050: long precision = value.getPrecision();
051: if (precision > 0) {
052: return precision;
053: }
054: }
055: long size = 0;
056: InputStream in = value.getInputStream();
057: try {
058: byte[] buff = new byte[Constants.FILE_BLOCK_SIZE];
059: while (true) {
060: int len = in.read(buff, 0,
061: Constants.FILE_BLOCK_SIZE);
062: if (len <= 0) {
063: break;
064: }
065: size += len;
066: }
067: } finally {
068: in.close();
069: }
070: return size;
071: } catch (Throwable e) {
072: throw logAndConvert(e);
073: }
074: }
075:
076: /**
077: * [Not supported] Truncates the object.
078: *
079: * @param len the new length
080: */
081: public void truncate(long len) throws SQLException {
082: debugCodeCall("truncate", len);
083: throw Message.getUnsupportedException();
084: }
085:
086: /**
087: * Returns some bytes of the object.
088: *
089: * @param pos the index, the first byte is at position 1
090: * @param length the number of bytes
091: * @return the bytes, at most length bytes
092: */
093: public byte[] getBytes(long pos, int length) throws SQLException {
094: try {
095: debugCode("getBytes(" + pos + ", " + length + ");");
096: checkClosed();
097: ByteArrayOutputStream out = new ByteArrayOutputStream();
098: InputStream in = value.getInputStream();
099: try {
100: IOUtils.skipFully(in, pos - 1);
101: while (length > 0) {
102: int x = in.read();
103: if (x < 0) {
104: break;
105: }
106: out.write(x);
107: length--;
108: }
109: } finally {
110: in.close();
111: }
112: return out.toByteArray();
113: } catch (Throwable e) {
114: throw logAndConvert(e);
115: }
116: }
117:
118: /**
119: * [Not supported] Sets some bytes of the object.
120: */
121: public int setBytes(long pos, byte[] bytes) throws SQLException {
122: debugCode("setBytes(" + pos + ", bytes);");
123: throw Message.getUnsupportedException();
124: }
125:
126: /**
127: * [Not supported] Sets some bytes of the object.
128: */
129: public int setBytes(long pos, byte[] bytes, int offset, int len)
130: throws SQLException {
131: debugCode("setBytes(" + pos + ", bytes, " + offset + ", " + len
132: + ");");
133: throw Message.getUnsupportedException();
134: }
135:
136: /**
137: * Returns the input stream.
138: *
139: * @return the input stream
140: */
141: public InputStream getBinaryStream() throws SQLException {
142: try {
143: debugCodeCall("getBinaryStream");
144: checkClosed();
145: return value.getInputStream();
146: } catch (Throwable e) {
147: throw logAndConvert(e);
148: }
149: }
150:
151: /**
152: * [Not supported] Returns an output stream.
153: */
154: public OutputStream setBinaryStream(long pos) throws SQLException {
155: debugCodeCall("setBinaryStream", pos);
156: throw Message.getUnsupportedException();
157: }
158:
159: /**
160: * [Not supported] Searches a pattern and return the position.
161: *
162: * @param pattern the pattern to search
163: * @param start the index, the first byte is at position 1
164: * @return the position (first byte is at position 1), or -1 for not found
165: */
166: public long position(byte[] pattern, long start)
167: throws SQLException {
168: debugCode("position(pattern, " + start + ");");
169: throw Message.getUnsupportedException();
170: // TODO test
171: // try {
172: // debugCode("position(pattern, "+start+");");
173: // if(pattern == null) {
174: // return -1;
175: // }
176: // if(pattern.length == 0) {
177: // return 1;
178: // }
179: // // TODO performance: blob pattern search is slow
180: // BufferedInputStream in =
181: // new BufferedInputStream(value.getInputStream());
182: // IOUtils.skipFully(in, start - 1);
183: // int pos = 0;
184: // int patternPos = 0;
185: // while(true) {
186: // int x = in.read();
187: // if(x<0) {
188: // break;
189: // }
190: // if(x == (pattern[patternPos] & 0xff)) {
191: // if(patternPos == 0) {
192: // in.mark(pattern.length);
193: // }
194: // if(patternPos == pattern.length) {
195: // return pos - patternPos;
196: // }
197: // patternPos++;
198: // } else {
199: // if(patternPos > 0) {
200: // in.reset();
201: // pos -= patternPos;
202: // }
203: // }
204: // pos++;
205: // }
206: // return -1;
207: // } catch(Throwable e) {
208: // throw logAndConvert(e);
209: // }
210: }
211:
212: /**
213: * [Not supported] Searches a pattern and return the position.
214: *
215: * @param blobPattern the pattern to search
216: * @param start the index, the first byte is at position 1
217: * @return the position (first byte is at position 1), or -1 for not found
218: */
219: public long position(Blob blobPattern, long start)
220: throws SQLException {
221: debugCode("position(blobPattern, " + start + ");");
222: throw Message.getUnsupportedException();
223:
224: // try {
225: // debugCode("position(blobPattern, "+start+");");
226: // if(blobPattern == null) {
227: // return -1;
228: // }
229: // ByteArrayOutputStream out = new ByteArrayOutputStream();
230: // InputStream in = blobPattern.getBinaryStream();
231: // while(true) {
232: // int x = in.read();
233: // if(x < 0) {
234: // break;
235: // }
236: // out.write(x);
237: // }
238: // return position(out.toByteArray(), start);
239: // } catch(Throwable e) {
240: // throw logAndConvert(e);
241: // }
242: }
243:
244: /**
245: * Release all resources of this object.
246: */
247: public void free() throws SQLException {
248: debugCodeCall("free");
249: value = null;
250: }
251:
252: /**
253: * [Not supported] Returns the input stream, starting from an offset.
254: */
255: public InputStream getBinaryStream(long pos, long length)
256: throws SQLException {
257: debugCode("getBinaryStream(" + pos + ", " + length + ");");
258: throw Message.getUnsupportedException();
259: }
260:
261: private void checkClosed() throws SQLException {
262: conn.checkClosed();
263: if (value == null) {
264: throw Message.getSQLException(ErrorCode.OBJECT_CLOSED);
265: }
266: }
267:
268: /**
269: * INTERNAL
270: */
271: public String toString() {
272: return getTraceObjectName() + ": " + value.getSQL();
273: }
274:
275: }
|